| Charles Davis | 74ce859 | 2010-06-09 23:25:41 +0000 | [diff] [blame] | 1 | //===--- 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 Lattner | 57540c5 | 2011-04-15 05:22:18 +0000 | [diff] [blame] | 10 | // This provides C++ code generation targeting the Microsoft Visual C++ ABI. | 
| Charles Davis | 74ce859 | 2010-06-09 23:25:41 +0000 | [diff] [blame] | 11 | // 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" | 
| Reid Kleckner | 10aa770 | 2015-09-16 20:15:55 +0000 | [diff] [blame] | 18 | #include "CGCleanup.h" | 
| Reid Kleckner | 7810af0 | 2013-06-19 15:20:38 +0000 | [diff] [blame] | 19 | #include "CGVTables.h" | 
| Chandler Carruth | 5553d0d | 2014-01-07 11:51:46 +0000 | [diff] [blame] | 20 | #include "CodeGenModule.h" | 
| David Majnemer | e7a818f | 2015-03-06 18:53:55 +0000 | [diff] [blame] | 21 | #include "CodeGenTypes.h" | 
| Reid Kleckner | fff8e7f | 2015-03-03 19:21:04 +0000 | [diff] [blame] | 22 | #include "TargetInfo.h" | 
| Charles Davis | 74ce859 | 2010-06-09 23:25:41 +0000 | [diff] [blame] | 23 | #include "clang/AST/Decl.h" | 
|  | 24 | #include "clang/AST/DeclCXX.h" | 
| Reid Kleckner | fff8e7f | 2015-03-03 19:21:04 +0000 | [diff] [blame] | 25 | #include "clang/AST/StmtCXX.h" | 
| Timur Iskhodzhanov | df7e7fb | 2013-07-30 09:46:19 +0000 | [diff] [blame] | 26 | #include "clang/AST/VTableBuilder.h" | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 27 | #include "llvm/ADT/StringExtras.h" | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 28 | #include "llvm/ADT/StringSet.h" | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 29 | #include "llvm/IR/CallSite.h" | 
| Reid Kleckner | fff8e7f | 2015-03-03 19:21:04 +0000 | [diff] [blame] | 30 | #include "llvm/IR/Intrinsics.h" | 
| Charles Davis | 74ce859 | 2010-06-09 23:25:41 +0000 | [diff] [blame] | 31 |  | 
|  | 32 | using namespace clang; | 
|  | 33 | using namespace CodeGen; | 
|  | 34 |  | 
|  | 35 | namespace { | 
|  | 36 |  | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 37 | /// Holds all the vbtable globals for a given class. | 
|  | 38 | struct VBTableGlobals { | 
| Reid Kleckner | 9c6e9e3 | 2014-02-27 19:40:09 +0000 | [diff] [blame] | 39 | const VPtrInfoVector *VBTables; | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 40 | SmallVector<llvm::GlobalVariable *, 2> Globals; | 
|  | 41 | }; | 
|  | 42 |  | 
| Charles Davis | 53c59df | 2010-08-16 03:33:14 +0000 | [diff] [blame] | 43 | class MicrosoftCXXABI : public CGCXXABI { | 
| Charles Davis | 74ce859 | 2010-06-09 23:25:41 +0000 | [diff] [blame] | 44 | public: | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 45 | MicrosoftCXXABI(CodeGenModule &CGM) | 
|  | 46 | : CGCXXABI(CGM), BaseClassDescriptorType(nullptr), | 
|  | 47 | ClassHierarchyDescriptorType(nullptr), | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 48 | CompleteObjectLocatorType(nullptr), CatchableTypeType(nullptr), | 
| Benjamin Kramer | c2d2b42 | 2015-10-15 15:29:40 +0000 | [diff] [blame] | 49 | ThrowInfoType(nullptr) {} | 
| John McCall | 5d865c32 | 2010-08-31 07:33:07 +0000 | [diff] [blame] | 50 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 51 | bool HasThisReturn(GlobalDecl GD) const override; | 
| David Majnemer | 0c0b6d9 | 2014-10-31 20:09:12 +0000 | [diff] [blame] | 52 | bool hasMostDerivedReturn(GlobalDecl GD) const override; | 
| Stephen Lin | 9dc6eef | 2013-06-30 20:40:16 +0000 | [diff] [blame] | 53 |  | 
| Reid Kleckner | 40ca913 | 2014-05-13 22:05:45 +0000 | [diff] [blame] | 54 | bool classifyReturnType(CGFunctionInfo &FI) const override; | 
| Timur Iskhodzhanov | 8fe501d | 2013-04-17 12:54:10 +0000 | [diff] [blame] | 55 |  | 
| Reid Kleckner | e39ee21 | 2014-05-03 00:33:28 +0000 | [diff] [blame] | 56 | RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override; | 
| Timur Iskhodzhanov | 8fe501d | 2013-04-17 12:54:10 +0000 | [diff] [blame] | 57 |  | 
| Reid Kleckner | 37abaca | 2014-05-09 22:46:15 +0000 | [diff] [blame] | 58 | bool isSRetParameterAfterThis() const override { return true; } | 
|  | 59 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 60 | bool isThisCompleteObject(GlobalDecl GD) const override { | 
|  | 61 | // The Microsoft ABI doesn't use separate complete-object vs. | 
|  | 62 | // base-object variants of constructors, but it does of destructors. | 
|  | 63 | if (isa<CXXDestructorDecl>(GD.getDecl())) { | 
|  | 64 | switch (GD.getDtorType()) { | 
|  | 65 | case Dtor_Complete: | 
|  | 66 | case Dtor_Deleting: | 
|  | 67 | return true; | 
|  | 68 |  | 
|  | 69 | case Dtor_Base: | 
|  | 70 | return false; | 
|  | 71 |  | 
|  | 72 | case Dtor_Comdat: llvm_unreachable("emitting dtor comdat as function?"); | 
|  | 73 | } | 
|  | 74 | llvm_unreachable("bad dtor kind"); | 
|  | 75 | } | 
|  | 76 |  | 
|  | 77 | // No other kinds. | 
|  | 78 | return false; | 
|  | 79 | } | 
|  | 80 |  | 
| David Majnemer | 196ac33 | 2014-09-11 23:05:02 +0000 | [diff] [blame] | 81 | size_t getSrcArgforCopyCtor(const CXXConstructorDecl *CD, | 
|  | 82 | FunctionArgList &Args) const override { | 
|  | 83 | assert(Args.size() >= 2 && | 
|  | 84 | "expected the arglist to have at least two args!"); | 
|  | 85 | // The 'most_derived' parameter goes second if the ctor is variadic and | 
|  | 86 | // has v-bases. | 
|  | 87 | if (CD->getParent()->getNumVBases() > 0 && | 
|  | 88 | CD->getType()->castAs<FunctionProtoType>()->isVariadic()) | 
|  | 89 | return 2; | 
|  | 90 | return 1; | 
|  | 91 | } | 
|  | 92 |  | 
| David Majnemer | 8671c6e | 2015-11-02 09:01:44 +0000 | [diff] [blame] | 93 | std::vector<CharUnits> getVBPtrOffsets(const CXXRecordDecl *RD) override { | 
|  | 94 | std::vector<CharUnits> VBPtrOffsets; | 
|  | 95 | const ASTContext &Context = getContext(); | 
|  | 96 | const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); | 
|  | 97 |  | 
|  | 98 | const VBTableGlobals &VBGlobals = enumerateVBTables(RD); | 
|  | 99 | for (const VPtrInfo *VBT : *VBGlobals.VBTables) { | 
|  | 100 | const ASTRecordLayout &SubobjectLayout = | 
|  | 101 | Context.getASTRecordLayout(VBT->BaseWithVPtr); | 
|  | 102 | CharUnits Offs = VBT->NonVirtualOffset; | 
|  | 103 | Offs += SubobjectLayout.getVBPtrOffset(); | 
|  | 104 | if (VBT->getVBaseWithVPtr()) | 
|  | 105 | Offs += Layout.getVBaseClassOffset(VBT->getVBaseWithVPtr()); | 
|  | 106 | VBPtrOffsets.push_back(Offs); | 
|  | 107 | } | 
|  | 108 | llvm::array_pod_sort(VBPtrOffsets.begin(), VBPtrOffsets.end()); | 
|  | 109 | return VBPtrOffsets; | 
|  | 110 | } | 
|  | 111 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 112 | StringRef GetPureVirtualCallName() override { return "_purecall"; } | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 113 | StringRef GetDeletedVirtualCallName() override { return "_purecall"; } | 
| Joao Matos | 2ce88ef | 2012-07-17 17:10:11 +0000 | [diff] [blame] | 114 |  | 
| David Majnemer | 0868137 | 2014-11-01 07:37:17 +0000 | [diff] [blame] | 115 | void emitVirtualObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 116 | Address Ptr, QualType ElementType, | 
| David Majnemer | 0c0b6d9 | 2014-10-31 20:09:12 +0000 | [diff] [blame] | 117 | const CXXDestructorDecl *Dtor) override; | 
| John McCall | 82fb892 | 2012-09-25 10:10:39 +0000 | [diff] [blame] | 118 |  | 
| Chandler Carruth | 4b9e857 | 2014-11-25 08:59:34 +0000 | [diff] [blame] | 119 | void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) override; | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 120 | void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) override; | 
| David Majnemer | 442d0a2 | 2014-11-25 07:20:20 +0000 | [diff] [blame] | 121 |  | 
| Reid Kleckner | fff8e7f | 2015-03-03 19:21:04 +0000 | [diff] [blame] | 122 | void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override; | 
|  | 123 |  | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 124 | llvm::GlobalVariable *getMSCompleteObjectLocator(const CXXRecordDecl *RD, | 
|  | 125 | const VPtrInfo *Info); | 
|  | 126 |  | 
| David Majnemer | 443250f | 2015-03-17 20:35:00 +0000 | [diff] [blame] | 127 | llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override; | 
| Reid Kleckner | 10aa770 | 2015-09-16 20:15:55 +0000 | [diff] [blame] | 128 | CatchTypeInfo | 
| David Majnemer | 37b417f | 2015-03-29 21:55:10 +0000 | [diff] [blame] | 129 | getAddrOfCXXCatchHandlerType(QualType Ty, QualType CatchHandlerType) override; | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 130 |  | 
| Reid Kleckner | 10aa770 | 2015-09-16 20:15:55 +0000 | [diff] [blame] | 131 | /// MSVC needs an extra flag to indicate a catchall. | 
|  | 132 | CatchTypeInfo getCatchAllTypeInfo() override { | 
|  | 133 | return CatchTypeInfo{nullptr, 0x40}; | 
|  | 134 | } | 
|  | 135 |  | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 136 | bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy) override; | 
|  | 137 | void EmitBadTypeidCall(CodeGenFunction &CGF) override; | 
|  | 138 | llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 139 | Address ThisPtr, | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 140 | llvm::Type *StdTypeInfoPtrTy) override; | 
|  | 141 |  | 
|  | 142 | bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr, | 
|  | 143 | QualType SrcRecordTy) override; | 
|  | 144 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 145 | llvm::Value *EmitDynamicCastCall(CodeGenFunction &CGF, Address Value, | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 146 | QualType SrcRecordTy, QualType DestTy, | 
|  | 147 | QualType DestRecordTy, | 
|  | 148 | llvm::BasicBlock *CastEnd) override; | 
|  | 149 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 150 | llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF, Address Value, | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 151 | QualType SrcRecordTy, | 
|  | 152 | QualType DestTy) override; | 
|  | 153 |  | 
|  | 154 | bool EmitBadCastCall(CodeGenFunction &CGF) override; | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 155 | bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override { | 
| Piotr Padlewski | a68a787 | 2015-07-24 04:04:49 +0000 | [diff] [blame] | 156 | return false; | 
|  | 157 | } | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 158 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 159 | llvm::Value * | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 160 | GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This, | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 161 | const CXXRecordDecl *ClassDecl, | 
|  | 162 | const CXXRecordDecl *BaseClassDecl) override; | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 163 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 164 | llvm::BasicBlock * | 
|  | 165 | EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, | 
|  | 166 | const CXXRecordDecl *RD) override; | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 167 |  | 
| Timur Iskhodzhanov | b648732 | 2013-10-09 18:16:58 +0000 | [diff] [blame] | 168 | void initializeHiddenVirtualInheritanceMembers(CodeGenFunction &CGF, | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 169 | const CXXRecordDecl *RD) override; | 
| Timur Iskhodzhanov | b648732 | 2013-10-09 18:16:58 +0000 | [diff] [blame] | 170 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 171 | void EmitCXXConstructors(const CXXConstructorDecl *D) override; | 
| Timur Iskhodzhanov | 40f2fa9 | 2013-08-04 17:30:04 +0000 | [diff] [blame] | 172 |  | 
| Reid Kleckner | e7de47e | 2013-07-22 13:51:44 +0000 | [diff] [blame] | 173 | // Background on MSVC destructors | 
|  | 174 | // ============================== | 
|  | 175 | // | 
|  | 176 | // Both Itanium and MSVC ABIs have destructor variants.  The variant names | 
|  | 177 | // roughly correspond in the following way: | 
|  | 178 | //   Itanium       Microsoft | 
|  | 179 | //   Base       -> no name, just ~Class | 
|  | 180 | //   Complete   -> vbase destructor | 
|  | 181 | //   Deleting   -> scalar deleting destructor | 
|  | 182 | //                 vector deleting destructor | 
|  | 183 | // | 
|  | 184 | // The base and complete destructors are the same as in Itanium, although the | 
|  | 185 | // complete destructor does not accept a VTT parameter when there are virtual | 
|  | 186 | // bases.  A separate mechanism involving vtordisps is used to ensure that | 
|  | 187 | // virtual methods of destroyed subobjects are not called. | 
|  | 188 | // | 
|  | 189 | // The deleting destructors accept an i32 bitfield as a second parameter.  Bit | 
|  | 190 | // 1 indicates if the memory should be deleted.  Bit 2 indicates if the this | 
|  | 191 | // pointer points to an array.  The scalar deleting destructor assumes that | 
|  | 192 | // bit 2 is zero, and therefore does not contain a loop. | 
|  | 193 | // | 
|  | 194 | // For virtual destructors, only one entry is reserved in the vftable, and it | 
|  | 195 | // always points to the vector deleting destructor.  The vector deleting | 
|  | 196 | // destructor is the most general, so it can be used to destroy objects in | 
|  | 197 | // place, delete single heap objects, or delete arrays. | 
|  | 198 | // | 
|  | 199 | // A TU defining a non-inline destructor is only guaranteed to emit a base | 
|  | 200 | // destructor, and all of the other variants are emitted on an as-needed basis | 
|  | 201 | // in COMDATs.  Because a non-base destructor can be emitted in a TU that | 
|  | 202 | // lacks a definition for the destructor, non-base destructors must always | 
|  | 203 | // delegate to or alias the base destructor. | 
|  | 204 |  | 
| Rafael Espindola | 8d2a19b | 2014-09-08 16:01:27 +0000 | [diff] [blame] | 205 | void buildStructorSignature(const CXXMethodDecl *MD, StructorType T, | 
|  | 206 | SmallVectorImpl<CanQualType> &ArgTys) override; | 
| John McCall | 5d865c32 | 2010-08-31 07:33:07 +0000 | [diff] [blame] | 207 |  | 
| Reid Kleckner | e7de47e | 2013-07-22 13:51:44 +0000 | [diff] [blame] | 208 | /// Non-base dtors should be emitted as delegating thunks in this ABI. | 
|  | 209 | bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor, | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 210 | CXXDtorType DT) const override { | 
| Reid Kleckner | e7de47e | 2013-07-22 13:51:44 +0000 | [diff] [blame] | 211 | return DT != Dtor_Base; | 
|  | 212 | } | 
|  | 213 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 214 | void EmitCXXDestructors(const CXXDestructorDecl *D) override; | 
| Reid Kleckner | e7de47e | 2013-07-22 13:51:44 +0000 | [diff] [blame] | 215 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 216 | const CXXRecordDecl * | 
|  | 217 | getThisArgumentTypeForMethod(const CXXMethodDecl *MD) override { | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 218 | MD = MD->getCanonicalDecl(); | 
|  | 219 | if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD)) { | 
| Timur Iskhodzhanov | 5877663 | 2013-11-05 15:54:58 +0000 | [diff] [blame] | 220 | MicrosoftVTableContext::MethodVFTableLocation ML = | 
|  | 221 | CGM.getMicrosoftVTableContext().getMethodVFTableLocation(MD); | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 222 | // The vbases might be ordered differently in the final overrider object | 
|  | 223 | // and the complete object, so the "this" argument may sometimes point to | 
|  | 224 | // memory that has no particular type (e.g. past the complete object). | 
|  | 225 | // In this case, we just use a generic pointer type. | 
|  | 226 | // FIXME: might want to have a more precise type in the non-virtual | 
|  | 227 | // multiple inheritance case. | 
| Timur Iskhodzhanov | 9e7f505 | 2013-11-07 13:34:02 +0000 | [diff] [blame] | 228 | if (ML.VBase || !ML.VFPtrOffset.isZero()) | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 229 | return nullptr; | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 230 | } | 
|  | 231 | return MD->getParent(); | 
|  | 232 | } | 
|  | 233 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 234 | Address | 
| Timur Iskhodzhanov | f174942 | 2014-03-14 17:43:37 +0000 | [diff] [blame] | 235 | adjustThisArgumentForVirtualFunctionCall(CodeGenFunction &CGF, GlobalDecl GD, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 236 | Address This, | 
| Timur Iskhodzhanov | f174942 | 2014-03-14 17:43:37 +0000 | [diff] [blame] | 237 | bool VirtualCall) override; | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 238 |  | 
| Reid Kleckner | 89077a1 | 2013-12-17 19:46:40 +0000 | [diff] [blame] | 239 | void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy, | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 240 | FunctionArgList &Params) override; | 
| John McCall | 5d865c32 | 2010-08-31 07:33:07 +0000 | [diff] [blame] | 241 |  | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 242 | llvm::Value *adjustThisParameterInVirtualFunctionPrologue( | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 243 | CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This) override; | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 244 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 245 | void EmitInstanceFunctionProlog(CodeGenFunction &CGF) override; | 
| John McCall | 2903675 | 2011-01-27 02:46:02 +0000 | [diff] [blame] | 246 |  | 
| Reid Kleckner | 89077a1 | 2013-12-17 19:46:40 +0000 | [diff] [blame] | 247 | unsigned addImplicitConstructorArgs(CodeGenFunction &CGF, | 
|  | 248 | const CXXConstructorDecl *D, | 
|  | 249 | CXXCtorType Type, bool ForVirtualBase, | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 250 | bool Delegating, | 
|  | 251 | CallArgList &Args) override; | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 252 |  | 
| Reid Kleckner | 6fe771a | 2013-12-13 00:53:54 +0000 | [diff] [blame] | 253 | void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, | 
|  | 254 | CXXDtorType Type, bool ForVirtualBase, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 255 | bool Delegating, Address This) override; | 
| Reid Kleckner | 6fe771a | 2013-12-13 00:53:54 +0000 | [diff] [blame] | 256 |  | 
| Peter Collingbourne | d954601 | 2015-06-19 02:30:43 +0000 | [diff] [blame] | 257 | void emitVTableBitSetEntries(VPtrInfo *Info, const CXXRecordDecl *RD, | 
|  | 258 | llvm::GlobalVariable *VTable); | 
|  | 259 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 260 | void emitVTableDefinitions(CodeGenVTables &CGVT, | 
|  | 261 | const CXXRecordDecl *RD) override; | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 262 |  | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 263 | bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF, | 
|  | 264 | CodeGenFunction::VPtr Vptr) override; | 
|  | 265 |  | 
|  | 266 | /// Don't initialize vptrs if dynamic class | 
|  | 267 | /// is marked with with the 'novtable' attribute. | 
|  | 268 | bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass) override { | 
|  | 269 | return !VTableClass->hasAttr<MSNoVTableAttr>(); | 
|  | 270 | } | 
|  | 271 |  | 
|  | 272 | llvm::Constant * | 
|  | 273 | getVTableAddressPoint(BaseSubobject Base, | 
|  | 274 | const CXXRecordDecl *VTableClass) override; | 
|  | 275 |  | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 276 | llvm::Value *getVTableAddressPointInStructor( | 
|  | 277 | CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 278 | BaseSubobject Base, const CXXRecordDecl *NearestVBase) override; | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 279 |  | 
|  | 280 | llvm::Constant * | 
|  | 281 | getVTableAddressPointForConstExpr(BaseSubobject Base, | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 282 | const CXXRecordDecl *VTableClass) override; | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 283 |  | 
|  | 284 | llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 285 | CharUnits VPtrOffset) override; | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 286 |  | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 287 | llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 288 | Address This, llvm::Type *Ty, | 
| Peter Collingbourne | 6708c4a | 2015-06-19 01:51:54 +0000 | [diff] [blame] | 289 | SourceLocation Loc) override; | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 290 |  | 
| David Majnemer | 0c0b6d9 | 2014-10-31 20:09:12 +0000 | [diff] [blame] | 291 | llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF, | 
|  | 292 | const CXXDestructorDecl *Dtor, | 
|  | 293 | CXXDtorType DtorType, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 294 | Address This, | 
| David Majnemer | 0c0b6d9 | 2014-10-31 20:09:12 +0000 | [diff] [blame] | 295 | const CXXMemberCallExpr *CE) override; | 
| Timur Iskhodzhanov | d619711 | 2013-02-15 14:45:22 +0000 | [diff] [blame] | 296 |  | 
| Timur Iskhodzhanov | ad9d3b8 | 2013-10-09 09:23:58 +0000 | [diff] [blame] | 297 | void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD, | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 298 | CallArgList &CallArgs) override { | 
| Timur Iskhodzhanov | ad9d3b8 | 2013-10-09 09:23:58 +0000 | [diff] [blame] | 299 | assert(GD.getDtorType() == Dtor_Deleting && | 
|  | 300 | "Only deleting destructor thunks are available in this ABI"); | 
|  | 301 | CallArgs.add(RValue::get(getStructorImplicitParamValue(CGF)), | 
| David Majnemer | 9ced3dd | 2015-03-14 23:44:48 +0000 | [diff] [blame] | 302 | getContext().IntTy); | 
| Timur Iskhodzhanov | ad9d3b8 | 2013-10-09 09:23:58 +0000 | [diff] [blame] | 303 | } | 
|  | 304 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 305 | void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override; | 
| Reid Kleckner | 7810af0 | 2013-06-19 15:20:38 +0000 | [diff] [blame] | 306 |  | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 307 | llvm::GlobalVariable * | 
| Reid Kleckner | 9c6e9e3 | 2014-02-27 19:40:09 +0000 | [diff] [blame] | 308 | getAddrOfVBTable(const VPtrInfo &VBT, const CXXRecordDecl *RD, | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 309 | llvm::GlobalVariable::LinkageTypes Linkage); | 
|  | 310 |  | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 311 | llvm::GlobalVariable * | 
|  | 312 | getAddrOfVirtualDisplacementMap(const CXXRecordDecl *SrcRD, | 
|  | 313 | const CXXRecordDecl *DstRD) { | 
|  | 314 | SmallString<256> OutName; | 
|  | 315 | llvm::raw_svector_ostream Out(OutName); | 
|  | 316 | getMangleContext().mangleCXXVirtualDisplacementMap(SrcRD, DstRD, Out); | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 317 | StringRef MangledName = OutName.str(); | 
|  | 318 |  | 
|  | 319 | if (auto *VDispMap = CGM.getModule().getNamedGlobal(MangledName)) | 
|  | 320 | return VDispMap; | 
|  | 321 |  | 
|  | 322 | MicrosoftVTableContext &VTContext = CGM.getMicrosoftVTableContext(); | 
|  | 323 | unsigned NumEntries = 1 + SrcRD->getNumVBases(); | 
|  | 324 | SmallVector<llvm::Constant *, 4> Map(NumEntries, | 
|  | 325 | llvm::UndefValue::get(CGM.IntTy)); | 
|  | 326 | Map[0] = llvm::ConstantInt::get(CGM.IntTy, 0); | 
|  | 327 | bool AnyDifferent = false; | 
|  | 328 | for (const auto &I : SrcRD->vbases()) { | 
|  | 329 | const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl(); | 
|  | 330 | if (!DstRD->isVirtuallyDerivedFrom(VBase)) | 
|  | 331 | continue; | 
|  | 332 |  | 
|  | 333 | unsigned SrcVBIndex = VTContext.getVBTableIndex(SrcRD, VBase); | 
|  | 334 | unsigned DstVBIndex = VTContext.getVBTableIndex(DstRD, VBase); | 
|  | 335 | Map[SrcVBIndex] = llvm::ConstantInt::get(CGM.IntTy, DstVBIndex * 4); | 
|  | 336 | AnyDifferent |= SrcVBIndex != DstVBIndex; | 
|  | 337 | } | 
|  | 338 | // This map would be useless, don't use it. | 
|  | 339 | if (!AnyDifferent) | 
|  | 340 | return nullptr; | 
|  | 341 |  | 
|  | 342 | llvm::ArrayType *VDispMapTy = llvm::ArrayType::get(CGM.IntTy, Map.size()); | 
|  | 343 | llvm::Constant *Init = llvm::ConstantArray::get(VDispMapTy, Map); | 
|  | 344 | llvm::GlobalValue::LinkageTypes Linkage = | 
|  | 345 | SrcRD->isExternallyVisible() && DstRD->isExternallyVisible() | 
|  | 346 | ? llvm::GlobalValue::LinkOnceODRLinkage | 
|  | 347 | : llvm::GlobalValue::InternalLinkage; | 
|  | 348 | auto *VDispMap = new llvm::GlobalVariable( | 
|  | 349 | CGM.getModule(), VDispMapTy, /*Constant=*/true, Linkage, | 
|  | 350 | /*Initializer=*/Init, MangledName); | 
|  | 351 | return VDispMap; | 
|  | 352 | } | 
|  | 353 |  | 
| Reid Kleckner | 9c6e9e3 | 2014-02-27 19:40:09 +0000 | [diff] [blame] | 354 | void emitVBTableDefinition(const VPtrInfo &VBT, const CXXRecordDecl *RD, | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 355 | llvm::GlobalVariable *GV) const; | 
|  | 356 |  | 
| Hans Wennborg | c94391d | 2014-06-06 20:04:01 +0000 | [diff] [blame] | 357 | void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, | 
|  | 358 | GlobalDecl GD, bool ReturnAdjustment) override { | 
| Hans Wennborg | 853ae94 | 2014-05-30 16:59:42 +0000 | [diff] [blame] | 359 | // Never dllimport/dllexport thunks. | 
|  | 360 | Thunk->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); | 
| Hans Wennborg | c94391d | 2014-06-06 20:04:01 +0000 | [diff] [blame] | 361 |  | 
|  | 362 | GVALinkage Linkage = | 
|  | 363 | getContext().GetGVALinkageForFunction(cast<FunctionDecl>(GD.getDecl())); | 
|  | 364 |  | 
|  | 365 | if (Linkage == GVA_Internal) | 
|  | 366 | Thunk->setLinkage(llvm::GlobalValue::InternalLinkage); | 
|  | 367 | else if (ReturnAdjustment) | 
|  | 368 | Thunk->setLinkage(llvm::GlobalValue::WeakODRLinkage); | 
|  | 369 | else | 
|  | 370 | Thunk->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage); | 
| Timur Iskhodzhanov | ad9d3b8 | 2013-10-09 09:23:58 +0000 | [diff] [blame] | 371 | } | 
|  | 372 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 373 | llvm::Value *performThisAdjustment(CodeGenFunction &CGF, Address This, | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 374 | const ThisAdjustment &TA) override; | 
| Timur Iskhodzhanov | 0201432 | 2013-10-30 11:55:43 +0000 | [diff] [blame] | 375 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 376 | llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, Address Ret, | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 377 | const ReturnAdjustment &RA) override; | 
| Timur Iskhodzhanov | 0201432 | 2013-10-30 11:55:43 +0000 | [diff] [blame] | 378 |  | 
| David Majnemer | b3341ea | 2014-10-05 05:05:40 +0000 | [diff] [blame] | 379 | void EmitThreadLocalInitFuncs( | 
| Richard Smith | 5a99c49 | 2015-12-01 01:10:48 +0000 | [diff] [blame] | 380 | CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals, | 
| David Majnemer | b3341ea | 2014-10-05 05:05:40 +0000 | [diff] [blame] | 381 | ArrayRef<llvm::Function *> CXXThreadLocalInits, | 
| Richard Smith | 5a99c49 | 2015-12-01 01:10:48 +0000 | [diff] [blame] | 382 | ArrayRef<const VarDecl *> CXXThreadLocalInitVars) override; | 
| David Majnemer | b3341ea | 2014-10-05 05:05:40 +0000 | [diff] [blame] | 383 |  | 
|  | 384 | bool usesThreadWrapperFunction() const override { return false; } | 
|  | 385 | LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD, | 
|  | 386 | QualType LValType) override; | 
|  | 387 |  | 
| John McCall | c84ed6a | 2012-05-01 06:13:13 +0000 | [diff] [blame] | 388 | void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, | 
|  | 389 | llvm::GlobalVariable *DeclPtr, | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 390 | bool PerformInit) override; | 
| David Majnemer | b3341ea | 2014-10-05 05:05:40 +0000 | [diff] [blame] | 391 | void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, | 
|  | 392 | llvm::Constant *Dtor, llvm::Constant *Addr) override; | 
| John McCall | c84ed6a | 2012-05-01 06:13:13 +0000 | [diff] [blame] | 393 |  | 
| John McCall | 2903675 | 2011-01-27 02:46:02 +0000 | [diff] [blame] | 394 | // ==== Notes on array cookies ========= | 
|  | 395 | // | 
|  | 396 | // MSVC seems to only use cookies when the class has a destructor; a | 
|  | 397 | // two-argument usual array deallocation function isn't sufficient. | 
|  | 398 | // | 
|  | 399 | // For example, this code prints "100" and "1": | 
|  | 400 | //   struct A { | 
|  | 401 | //     char x; | 
|  | 402 | //     void *operator new[](size_t sz) { | 
|  | 403 | //       printf("%u\n", sz); | 
|  | 404 | //       return malloc(sz); | 
|  | 405 | //     } | 
|  | 406 | //     void operator delete[](void *p, size_t sz) { | 
|  | 407 | //       printf("%u\n", sz); | 
|  | 408 | //       free(p); | 
|  | 409 | //     } | 
|  | 410 | //   }; | 
|  | 411 | //   int main() { | 
|  | 412 | //     A *p = new A[100]; | 
|  | 413 | //     delete[] p; | 
|  | 414 | //   } | 
|  | 415 | // Whereas it prints "104" and "104" if you give A a destructor. | 
| John McCall | b91cd66 | 2012-05-01 05:23:51 +0000 | [diff] [blame] | 416 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 417 | bool requiresArrayCookie(const CXXDeleteExpr *expr, | 
|  | 418 | QualType elementType) override; | 
|  | 419 | bool requiresArrayCookie(const CXXNewExpr *expr) override; | 
|  | 420 | CharUnits getArrayCookieSizeImpl(QualType type) override; | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 421 | Address InitializeArrayCookie(CodeGenFunction &CGF, | 
|  | 422 | Address NewPtr, | 
|  | 423 | llvm::Value *NumElements, | 
|  | 424 | const CXXNewExpr *expr, | 
|  | 425 | QualType ElementType) override; | 
| John McCall | b91cd66 | 2012-05-01 05:23:51 +0000 | [diff] [blame] | 426 | llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 427 | Address allocPtr, | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 428 | CharUnits cookieSize) override; | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 429 |  | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 430 | friend struct MSRTTIBuilder; | 
|  | 431 |  | 
|  | 432 | bool isImageRelative() const { | 
|  | 433 | return CGM.getTarget().getPointerWidth(/*AddressSpace=*/0) == 64; | 
|  | 434 | } | 
|  | 435 |  | 
|  | 436 | // 5 routines for constructing the llvm types for MS RTTI structs. | 
|  | 437 | llvm::StructType *getTypeDescriptorType(StringRef TypeInfoString) { | 
|  | 438 | llvm::SmallString<32> TDTypeName("rtti.TypeDescriptor"); | 
|  | 439 | TDTypeName += llvm::utostr(TypeInfoString.size()); | 
|  | 440 | llvm::StructType *&TypeDescriptorType = | 
|  | 441 | TypeDescriptorTypeMap[TypeInfoString.size()]; | 
|  | 442 | if (TypeDescriptorType) | 
|  | 443 | return TypeDescriptorType; | 
|  | 444 | llvm::Type *FieldTypes[] = { | 
|  | 445 | CGM.Int8PtrPtrTy, | 
|  | 446 | CGM.Int8PtrTy, | 
|  | 447 | llvm::ArrayType::get(CGM.Int8Ty, TypeInfoString.size() + 1)}; | 
|  | 448 | TypeDescriptorType = | 
|  | 449 | llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, TDTypeName); | 
|  | 450 | return TypeDescriptorType; | 
|  | 451 | } | 
|  | 452 |  | 
|  | 453 | llvm::Type *getImageRelativeType(llvm::Type *PtrType) { | 
|  | 454 | if (!isImageRelative()) | 
|  | 455 | return PtrType; | 
|  | 456 | return CGM.IntTy; | 
|  | 457 | } | 
|  | 458 |  | 
|  | 459 | llvm::StructType *getBaseClassDescriptorType() { | 
|  | 460 | if (BaseClassDescriptorType) | 
|  | 461 | return BaseClassDescriptorType; | 
|  | 462 | llvm::Type *FieldTypes[] = { | 
|  | 463 | getImageRelativeType(CGM.Int8PtrTy), | 
|  | 464 | CGM.IntTy, | 
|  | 465 | CGM.IntTy, | 
|  | 466 | CGM.IntTy, | 
|  | 467 | CGM.IntTy, | 
|  | 468 | CGM.IntTy, | 
|  | 469 | getImageRelativeType(getClassHierarchyDescriptorType()->getPointerTo()), | 
|  | 470 | }; | 
|  | 471 | BaseClassDescriptorType = llvm::StructType::create( | 
|  | 472 | CGM.getLLVMContext(), FieldTypes, "rtti.BaseClassDescriptor"); | 
|  | 473 | return BaseClassDescriptorType; | 
|  | 474 | } | 
|  | 475 |  | 
|  | 476 | llvm::StructType *getClassHierarchyDescriptorType() { | 
|  | 477 | if (ClassHierarchyDescriptorType) | 
|  | 478 | return ClassHierarchyDescriptorType; | 
|  | 479 | // Forward-declare RTTIClassHierarchyDescriptor to break a cycle. | 
|  | 480 | ClassHierarchyDescriptorType = llvm::StructType::create( | 
|  | 481 | CGM.getLLVMContext(), "rtti.ClassHierarchyDescriptor"); | 
|  | 482 | llvm::Type *FieldTypes[] = { | 
|  | 483 | CGM.IntTy, | 
|  | 484 | CGM.IntTy, | 
|  | 485 | CGM.IntTy, | 
|  | 486 | getImageRelativeType( | 
|  | 487 | getBaseClassDescriptorType()->getPointerTo()->getPointerTo()), | 
|  | 488 | }; | 
|  | 489 | ClassHierarchyDescriptorType->setBody(FieldTypes); | 
|  | 490 | return ClassHierarchyDescriptorType; | 
|  | 491 | } | 
|  | 492 |  | 
|  | 493 | llvm::StructType *getCompleteObjectLocatorType() { | 
|  | 494 | if (CompleteObjectLocatorType) | 
|  | 495 | return CompleteObjectLocatorType; | 
|  | 496 | CompleteObjectLocatorType = llvm::StructType::create( | 
|  | 497 | CGM.getLLVMContext(), "rtti.CompleteObjectLocator"); | 
|  | 498 | llvm::Type *FieldTypes[] = { | 
|  | 499 | CGM.IntTy, | 
|  | 500 | CGM.IntTy, | 
|  | 501 | CGM.IntTy, | 
|  | 502 | getImageRelativeType(CGM.Int8PtrTy), | 
|  | 503 | getImageRelativeType(getClassHierarchyDescriptorType()->getPointerTo()), | 
|  | 504 | getImageRelativeType(CompleteObjectLocatorType), | 
|  | 505 | }; | 
|  | 506 | llvm::ArrayRef<llvm::Type *> FieldTypesRef(FieldTypes); | 
|  | 507 | if (!isImageRelative()) | 
|  | 508 | FieldTypesRef = FieldTypesRef.drop_back(); | 
|  | 509 | CompleteObjectLocatorType->setBody(FieldTypesRef); | 
|  | 510 | return CompleteObjectLocatorType; | 
|  | 511 | } | 
|  | 512 |  | 
|  | 513 | llvm::GlobalVariable *getImageBase() { | 
|  | 514 | StringRef Name = "__ImageBase"; | 
|  | 515 | if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name)) | 
|  | 516 | return GV; | 
|  | 517 |  | 
|  | 518 | return new llvm::GlobalVariable(CGM.getModule(), CGM.Int8Ty, | 
|  | 519 | /*isConstant=*/true, | 
|  | 520 | llvm::GlobalValue::ExternalLinkage, | 
|  | 521 | /*Initializer=*/nullptr, Name); | 
|  | 522 | } | 
|  | 523 |  | 
|  | 524 | llvm::Constant *getImageRelativeConstant(llvm::Constant *PtrVal) { | 
|  | 525 | if (!isImageRelative()) | 
|  | 526 | return PtrVal; | 
|  | 527 |  | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 528 | if (PtrVal->isNullValue()) | 
|  | 529 | return llvm::Constant::getNullValue(CGM.IntTy); | 
|  | 530 |  | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 531 | llvm::Constant *ImageBaseAsInt = | 
|  | 532 | llvm::ConstantExpr::getPtrToInt(getImageBase(), CGM.IntPtrTy); | 
|  | 533 | llvm::Constant *PtrValAsInt = | 
|  | 534 | llvm::ConstantExpr::getPtrToInt(PtrVal, CGM.IntPtrTy); | 
|  | 535 | llvm::Constant *Diff = | 
|  | 536 | llvm::ConstantExpr::getSub(PtrValAsInt, ImageBaseAsInt, | 
|  | 537 | /*HasNUW=*/true, /*HasNSW=*/true); | 
|  | 538 | return llvm::ConstantExpr::getTrunc(Diff, CGM.IntTy); | 
|  | 539 | } | 
|  | 540 |  | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 541 | private: | 
| Timur Iskhodzhanov | 6745522 | 2013-10-03 06:26:13 +0000 | [diff] [blame] | 542 | MicrosoftMangleContext &getMangleContext() { | 
|  | 543 | return cast<MicrosoftMangleContext>(CodeGen::CGCXXABI::getMangleContext()); | 
|  | 544 | } | 
|  | 545 |  | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 546 | llvm::Constant *getZeroInt() { | 
|  | 547 | return llvm::ConstantInt::get(CGM.IntTy, 0); | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 548 | } | 
|  | 549 |  | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 550 | llvm::Constant *getAllOnesInt() { | 
|  | 551 | return  llvm::Constant::getAllOnesValue(CGM.IntTy); | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 552 | } | 
|  | 553 |  | 
| Timur Iskhodzhanov | f174942 | 2014-03-14 17:43:37 +0000 | [diff] [blame] | 554 | CharUnits getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD); | 
|  | 555 |  | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 556 | void | 
|  | 557 | GetNullMemberPointerFields(const MemberPointerType *MPT, | 
|  | 558 | llvm::SmallVectorImpl<llvm::Constant *> &fields); | 
|  | 559 |  | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 560 | /// \brief Shared code for virtual base adjustment.  Returns the offset from | 
|  | 561 | /// the vbptr to the virtual base.  Optionally returns the address of the | 
|  | 562 | /// vbptr itself. | 
|  | 563 | llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 564 | Address Base, | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 565 | llvm::Value *VBPtrOffset, | 
|  | 566 | llvm::Value *VBTableOffset, | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 567 | llvm::Value **VBPtr = nullptr); | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 568 |  | 
| Timur Iskhodzhanov | 0201432 | 2013-10-30 11:55:43 +0000 | [diff] [blame] | 569 | llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 570 | Address Base, | 
| Timur Iskhodzhanov | 0201432 | 2013-10-30 11:55:43 +0000 | [diff] [blame] | 571 | int32_t VBPtrOffset, | 
|  | 572 | int32_t VBTableOffset, | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 573 | llvm::Value **VBPtr = nullptr) { | 
| Reid Kleckner | 0ba8ba4 | 2014-10-22 17:26:00 +0000 | [diff] [blame] | 574 | assert(VBTableOffset % 4 == 0 && "should be byte offset into table of i32s"); | 
| Timur Iskhodzhanov | 0201432 | 2013-10-30 11:55:43 +0000 | [diff] [blame] | 575 | llvm::Value *VBPOffset = llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset), | 
|  | 576 | *VBTOffset = llvm::ConstantInt::get(CGM.IntTy, VBTableOffset); | 
|  | 577 | return GetVBaseOffsetFromVBPtr(CGF, Base, VBPOffset, VBTOffset, VBPtr); | 
|  | 578 | } | 
|  | 579 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 580 | std::pair<Address, llvm::Value *> | 
|  | 581 | performBaseAdjustment(CodeGenFunction &CGF, Address Value, | 
| David Majnemer | 5bc883f | 2015-02-27 02:38:02 +0000 | [diff] [blame] | 582 | QualType SrcRecordTy); | 
|  | 583 |  | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 584 | /// \brief Performs a full virtual base adjustment.  Used to dereference | 
|  | 585 | /// pointers to members of virtual bases. | 
| David Majnemer | 2b0d66d | 2014-02-20 23:22:07 +0000 | [diff] [blame] | 586 | llvm::Value *AdjustVirtualBase(CodeGenFunction &CGF, const Expr *E, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 587 | const CXXRecordDecl *RD, Address Base, | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 588 | llvm::Value *VirtualBaseAdjustmentOffset, | 
|  | 589 | llvm::Value *VBPtrOffset /* optional */); | 
|  | 590 |  | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 591 | /// \brief Emits a full member pointer with the fields common to data and | 
|  | 592 | /// function member pointers. | 
|  | 593 | llvm::Constant *EmitFullMemberPointer(llvm::Constant *FirstField, | 
|  | 594 | bool IsMemberFunction, | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 595 | const CXXRecordDecl *RD, | 
| David Majnemer | e60813f | 2015-05-10 21:48:08 +0000 | [diff] [blame] | 596 | CharUnits NonVirtualBaseAdjustment, | 
|  | 597 | unsigned VBTableIndex); | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 598 |  | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 599 | bool MemberPointerConstantIsNull(const MemberPointerType *MPT, | 
|  | 600 | llvm::Constant *MP); | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 601 |  | 
| Reid Kleckner | 7810af0 | 2013-06-19 15:20:38 +0000 | [diff] [blame] | 602 | /// \brief - Initialize all vbptrs of 'this' with RD as the complete type. | 
|  | 603 | void EmitVBPtrStores(CodeGenFunction &CGF, const CXXRecordDecl *RD); | 
|  | 604 |  | 
|  | 605 | /// \brief Caching wrapper around VBTableBuilder::enumerateVBTables(). | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 606 | const VBTableGlobals &enumerateVBTables(const CXXRecordDecl *RD); | 
| Reid Kleckner | 7810af0 | 2013-06-19 15:20:38 +0000 | [diff] [blame] | 607 |  | 
| Hans Wennborg | 88497d6 | 2013-11-15 17:24:45 +0000 | [diff] [blame] | 608 | /// \brief Generate a thunk for calling a virtual member function MD. | 
| Reid Kleckner | e4a5220 | 2014-02-21 02:27:32 +0000 | [diff] [blame] | 609 | llvm::Function *EmitVirtualMemPtrThunk( | 
|  | 610 | const CXXMethodDecl *MD, | 
|  | 611 | const MicrosoftVTableContext::MethodVFTableLocation &ML); | 
| Hans Wennborg | 88497d6 | 2013-11-15 17:24:45 +0000 | [diff] [blame] | 612 |  | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 613 | public: | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 614 | llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT) override; | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 615 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 616 | bool isZeroInitializable(const MemberPointerType *MPT) override; | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 617 |  | 
| David Majnemer | b3e5654 | 2014-08-07 22:56:13 +0000 | [diff] [blame] | 618 | bool isMemberPointerConvertible(const MemberPointerType *MPT) const override { | 
|  | 619 | const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); | 
| David Majnemer | 9928106 | 2014-09-18 22:05:54 +0000 | [diff] [blame] | 620 | return RD->hasAttr<MSInheritanceAttr>(); | 
|  | 621 | } | 
|  | 622 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 623 | llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT) override; | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 624 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 625 | llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT, | 
|  | 626 | CharUnits offset) override; | 
| David Majnemer | e2be95b | 2015-06-23 07:31:01 +0000 | [diff] [blame] | 627 | llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD) override; | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 628 | llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT) override; | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 629 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 630 | llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF, | 
|  | 631 | llvm::Value *L, | 
|  | 632 | llvm::Value *R, | 
|  | 633 | const MemberPointerType *MPT, | 
|  | 634 | bool Inequality) override; | 
| Reid Kleckner | 700c3ee | 2013-04-30 20:15:14 +0000 | [diff] [blame] | 635 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 636 | llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF, | 
|  | 637 | llvm::Value *MemPtr, | 
|  | 638 | const MemberPointerType *MPT) override; | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 639 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 640 | llvm::Value * | 
| David Majnemer | 2b0d66d | 2014-02-20 23:22:07 +0000 | [diff] [blame] | 641 | EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 642 | Address Base, llvm::Value *MemPtr, | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 643 | const MemberPointerType *MPT) override; | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 644 |  | 
| David Majnemer | 0d9ad68 | 2015-06-29 00:06:50 +0000 | [diff] [blame] | 645 | llvm::Value *EmitNonNullMemberPointerConversion( | 
|  | 646 | const MemberPointerType *SrcTy, const MemberPointerType *DstTy, | 
|  | 647 | CastKind CK, CastExpr::path_const_iterator PathBegin, | 
|  | 648 | CastExpr::path_const_iterator PathEnd, llvm::Value *Src, | 
|  | 649 | CGBuilderTy &Builder); | 
|  | 650 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 651 | llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF, | 
|  | 652 | const CastExpr *E, | 
|  | 653 | llvm::Value *Src) override; | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 654 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 655 | llvm::Constant *EmitMemberPointerConversion(const CastExpr *E, | 
|  | 656 | llvm::Constant *Src) override; | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 657 |  | 
| David Majnemer | 5ca193c | 2015-06-23 07:31:07 +0000 | [diff] [blame] | 658 | llvm::Constant *EmitMemberPointerConversion( | 
|  | 659 | const MemberPointerType *SrcTy, const MemberPointerType *DstTy, | 
|  | 660 | CastKind CK, CastExpr::path_const_iterator PathBegin, | 
|  | 661 | CastExpr::path_const_iterator PathEnd, llvm::Constant *Src); | 
|  | 662 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 663 | llvm::Value * | 
| David Majnemer | 2b0d66d | 2014-02-20 23:22:07 +0000 | [diff] [blame] | 664 | EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 665 | Address This, llvm::Value *&ThisPtrForCall, | 
|  | 666 | llvm::Value *MemPtr, | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 667 | const MemberPointerType *MPT) override; | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 668 |  | 
| Rafael Espindola | 91f68b4 | 2014-09-15 19:20:10 +0000 | [diff] [blame] | 669 | void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override; | 
|  | 670 |  | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 671 | llvm::StructType *getCatchableTypeType() { | 
|  | 672 | if (CatchableTypeType) | 
|  | 673 | return CatchableTypeType; | 
|  | 674 | llvm::Type *FieldTypes[] = { | 
|  | 675 | CGM.IntTy,                           // Flags | 
|  | 676 | getImageRelativeType(CGM.Int8PtrTy), // TypeDescriptor | 
|  | 677 | CGM.IntTy,                           // NonVirtualAdjustment | 
|  | 678 | CGM.IntTy,                           // OffsetToVBPtr | 
|  | 679 | CGM.IntTy,                           // VBTableIndex | 
|  | 680 | CGM.IntTy,                           // Size | 
|  | 681 | getImageRelativeType(CGM.Int8PtrTy)  // CopyCtor | 
|  | 682 | }; | 
|  | 683 | CatchableTypeType = llvm::StructType::create( | 
|  | 684 | CGM.getLLVMContext(), FieldTypes, "eh.CatchableType"); | 
|  | 685 | return CatchableTypeType; | 
|  | 686 | } | 
|  | 687 |  | 
|  | 688 | llvm::StructType *getCatchableTypeArrayType(uint32_t NumEntries) { | 
|  | 689 | llvm::StructType *&CatchableTypeArrayType = | 
|  | 690 | CatchableTypeArrayTypeMap[NumEntries]; | 
|  | 691 | if (CatchableTypeArrayType) | 
|  | 692 | return CatchableTypeArrayType; | 
|  | 693 |  | 
|  | 694 | llvm::SmallString<23> CTATypeName("eh.CatchableTypeArray."); | 
|  | 695 | CTATypeName += llvm::utostr(NumEntries); | 
|  | 696 | llvm::Type *CTType = | 
|  | 697 | getImageRelativeType(getCatchableTypeType()->getPointerTo()); | 
|  | 698 | llvm::Type *FieldTypes[] = { | 
|  | 699 | CGM.IntTy,                               // NumEntries | 
|  | 700 | llvm::ArrayType::get(CTType, NumEntries) // CatchableTypes | 
|  | 701 | }; | 
|  | 702 | CatchableTypeArrayType = | 
|  | 703 | llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, CTATypeName); | 
|  | 704 | return CatchableTypeArrayType; | 
|  | 705 | } | 
|  | 706 |  | 
|  | 707 | llvm::StructType *getThrowInfoType() { | 
|  | 708 | if (ThrowInfoType) | 
|  | 709 | return ThrowInfoType; | 
|  | 710 | llvm::Type *FieldTypes[] = { | 
|  | 711 | CGM.IntTy,                           // Flags | 
|  | 712 | getImageRelativeType(CGM.Int8PtrTy), // CleanupFn | 
|  | 713 | getImageRelativeType(CGM.Int8PtrTy), // ForwardCompat | 
|  | 714 | getImageRelativeType(CGM.Int8PtrTy)  // CatchableTypeArray | 
|  | 715 | }; | 
|  | 716 | ThrowInfoType = llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, | 
|  | 717 | "eh.ThrowInfo"); | 
|  | 718 | return ThrowInfoType; | 
|  | 719 | } | 
|  | 720 |  | 
|  | 721 | llvm::Constant *getThrowFn() { | 
|  | 722 | // _CxxThrowException is passed an exception object and a ThrowInfo object | 
|  | 723 | // which describes the exception. | 
|  | 724 | llvm::Type *Args[] = {CGM.Int8PtrTy, getThrowInfoType()->getPointerTo()}; | 
|  | 725 | llvm::FunctionType *FTy = | 
|  | 726 | llvm::FunctionType::get(CGM.VoidTy, Args, /*IsVarArgs=*/false); | 
|  | 727 | auto *Fn = cast<llvm::Function>( | 
|  | 728 | CGM.CreateRuntimeFunction(FTy, "_CxxThrowException")); | 
|  | 729 | // _CxxThrowException is stdcall on 32-bit x86 platforms. | 
|  | 730 | if (CGM.getTarget().getTriple().getArch() == llvm::Triple::x86) | 
|  | 731 | Fn->setCallingConv(llvm::CallingConv::X86_StdCall); | 
|  | 732 | return Fn; | 
|  | 733 | } | 
|  | 734 |  | 
| David Majnemer | 37fd66e | 2015-03-13 22:36:55 +0000 | [diff] [blame] | 735 | llvm::Function *getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD, | 
|  | 736 | CXXCtorType CT); | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 737 |  | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 738 | llvm::Constant *getCatchableType(QualType T, | 
|  | 739 | uint32_t NVOffset = 0, | 
|  | 740 | int32_t VBPtrOffset = -1, | 
|  | 741 | uint32_t VBIndex = 0); | 
|  | 742 |  | 
|  | 743 | llvm::GlobalVariable *getCatchableTypeArray(QualType T); | 
|  | 744 |  | 
| David Majnemer | ba3e5ec | 2015-03-13 18:26:17 +0000 | [diff] [blame] | 745 | llvm::GlobalVariable *getThrowInfo(QualType T) override; | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 746 |  | 
| Reid Kleckner | 7810af0 | 2013-06-19 15:20:38 +0000 | [diff] [blame] | 747 | private: | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 748 | typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy; | 
| David Majnemer | d905da4 | 2014-07-01 20:30:31 +0000 | [diff] [blame] | 749 | typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *> VTablesMapTy; | 
|  | 750 | typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalValue *> VFTablesMapTy; | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 751 | /// \brief All the vftables that have been referenced. | 
|  | 752 | VFTablesMapTy VFTablesMap; | 
| David Majnemer | d905da4 | 2014-07-01 20:30:31 +0000 | [diff] [blame] | 753 | VTablesMapTy VTablesMap; | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 754 |  | 
|  | 755 | /// \brief This set holds the record decls we've deferred vtable emission for. | 
|  | 756 | llvm::SmallPtrSet<const CXXRecordDecl *, 4> DeferredVFTables; | 
|  | 757 |  | 
|  | 758 |  | 
|  | 759 | /// \brief All the vbtables which have been referenced. | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 760 | llvm::DenseMap<const CXXRecordDecl *, VBTableGlobals> VBTablesMap; | 
| Reid Kleckner | d8110b6 | 2013-09-10 20:14:30 +0000 | [diff] [blame] | 761 |  | 
|  | 762 | /// Info on the global variable used to guard initialization of static locals. | 
|  | 763 | /// The BitIndex field is only used for externally invisible declarations. | 
|  | 764 | struct GuardInfo { | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 765 | GuardInfo() : Guard(nullptr), BitIndex(0) {} | 
| Reid Kleckner | d8110b6 | 2013-09-10 20:14:30 +0000 | [diff] [blame] | 766 | llvm::GlobalVariable *Guard; | 
|  | 767 | unsigned BitIndex; | 
|  | 768 | }; | 
|  | 769 |  | 
|  | 770 | /// Map from DeclContext to the current guard variable.  We assume that the | 
|  | 771 | /// AST is visited in source code order. | 
|  | 772 | llvm::DenseMap<const DeclContext *, GuardInfo> GuardVariableMap; | 
| David Majnemer | ec8e54b | 2015-05-07 21:19:06 +0000 | [diff] [blame] | 773 | llvm::DenseMap<const DeclContext *, GuardInfo> ThreadLocalGuardVariableMap; | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 774 | llvm::DenseMap<const DeclContext *, unsigned> ThreadSafeGuardNumMap; | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 775 |  | 
|  | 776 | llvm::DenseMap<size_t, llvm::StructType *> TypeDescriptorTypeMap; | 
|  | 777 | llvm::StructType *BaseClassDescriptorType; | 
|  | 778 | llvm::StructType *ClassHierarchyDescriptorType; | 
|  | 779 | llvm::StructType *CompleteObjectLocatorType; | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 780 |  | 
|  | 781 | llvm::DenseMap<QualType, llvm::GlobalVariable *> CatchableTypeArrays; | 
|  | 782 |  | 
|  | 783 | llvm::StructType *CatchableTypeType; | 
|  | 784 | llvm::DenseMap<uint32_t, llvm::StructType *> CatchableTypeArrayTypeMap; | 
|  | 785 | llvm::StructType *ThrowInfoType; | 
| Charles Davis | 74ce859 | 2010-06-09 23:25:41 +0000 | [diff] [blame] | 786 | }; | 
|  | 787 |  | 
| Alexander Kornienko | ab9db51 | 2015-06-22 23:07:51 +0000 | [diff] [blame] | 788 | } | 
| Charles Davis | 74ce859 | 2010-06-09 23:25:41 +0000 | [diff] [blame] | 789 |  | 
| Reid Kleckner | e39ee21 | 2014-05-03 00:33:28 +0000 | [diff] [blame] | 790 | CGCXXABI::RecordArgABI | 
|  | 791 | MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const { | 
|  | 792 | switch (CGM.getTarget().getTriple().getArch()) { | 
|  | 793 | default: | 
|  | 794 | // FIXME: Implement for other architectures. | 
|  | 795 | return RAA_Default; | 
|  | 796 |  | 
|  | 797 | case llvm::Triple::x86: | 
| Reid Kleckner | cf87e10 | 2014-05-14 16:02:09 +0000 | [diff] [blame] | 798 | // All record arguments are passed in memory on x86.  Decide whether to | 
|  | 799 | // construct the object directly in argument memory, or to construct the | 
|  | 800 | // argument elsewhere and copy the bytes during the call. | 
|  | 801 |  | 
|  | 802 | // If C++ prohibits us from making a copy, construct the arguments directly | 
|  | 803 | // into argument memory. | 
|  | 804 | if (!canCopyArgument(RD)) | 
| Reid Kleckner | e39ee21 | 2014-05-03 00:33:28 +0000 | [diff] [blame] | 805 | return RAA_DirectInMemory; | 
| Reid Kleckner | cf87e10 | 2014-05-14 16:02:09 +0000 | [diff] [blame] | 806 |  | 
|  | 807 | // Otherwise, construct the argument into a temporary and copy the bytes | 
|  | 808 | // into the outgoing argument memory. | 
| Reid Kleckner | e39ee21 | 2014-05-03 00:33:28 +0000 | [diff] [blame] | 809 | return RAA_Default; | 
|  | 810 |  | 
|  | 811 | case llvm::Triple::x86_64: | 
|  | 812 | // Win64 passes objects with non-trivial copy ctors indirectly. | 
|  | 813 | if (RD->hasNonTrivialCopyConstructor()) | 
|  | 814 | return RAA_Indirect; | 
| Reid Kleckner | cf87e10 | 2014-05-14 16:02:09 +0000 | [diff] [blame] | 815 |  | 
| Reid Kleckner | 80944df | 2014-10-31 22:00:51 +0000 | [diff] [blame] | 816 | // If an object has a destructor, we'd really like to pass it indirectly | 
|  | 817 | // because it allows us to elide copies.  Unfortunately, MSVC makes that | 
|  | 818 | // impossible for small types, which it will pass in a single register or | 
|  | 819 | // stack slot. Most objects with dtors are large-ish, so handle that early. | 
|  | 820 | // We can't call out all large objects as being indirect because there are | 
|  | 821 | // multiple x64 calling conventions and the C++ ABI code shouldn't dictate | 
|  | 822 | // how we pass large POD types. | 
|  | 823 | if (RD->hasNonTrivialDestructor() && | 
|  | 824 | getContext().getTypeSize(RD->getTypeForDecl()) > 64) | 
| Reid Kleckner | e39ee21 | 2014-05-03 00:33:28 +0000 | [diff] [blame] | 825 | return RAA_Indirect; | 
| Reid Kleckner | cf87e10 | 2014-05-14 16:02:09 +0000 | [diff] [blame] | 826 |  | 
|  | 827 | // We have a trivial copy constructor or no copy constructors, but we have | 
|  | 828 | // to make sure it isn't deleted. | 
|  | 829 | bool CopyDeleted = false; | 
|  | 830 | for (const CXXConstructorDecl *CD : RD->ctors()) { | 
|  | 831 | if (CD->isCopyConstructor()) { | 
|  | 832 | assert(CD->isTrivial()); | 
|  | 833 | // We had at least one undeleted trivial copy ctor.  Return directly. | 
|  | 834 | if (!CD->isDeleted()) | 
|  | 835 | return RAA_Default; | 
|  | 836 | CopyDeleted = true; | 
|  | 837 | } | 
|  | 838 | } | 
|  | 839 |  | 
|  | 840 | // The trivial copy constructor was deleted.  Return indirectly. | 
|  | 841 | if (CopyDeleted) | 
|  | 842 | return RAA_Indirect; | 
|  | 843 |  | 
|  | 844 | // There were no copy ctors.  Return in RAX. | 
| Reid Kleckner | e39ee21 | 2014-05-03 00:33:28 +0000 | [diff] [blame] | 845 | return RAA_Default; | 
|  | 846 | } | 
|  | 847 |  | 
|  | 848 | llvm_unreachable("invalid enum"); | 
|  | 849 | } | 
|  | 850 |  | 
| David Majnemer | 0868137 | 2014-11-01 07:37:17 +0000 | [diff] [blame] | 851 | void MicrosoftCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, | 
|  | 852 | const CXXDeleteExpr *DE, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 853 | Address Ptr, | 
| David Majnemer | 0868137 | 2014-11-01 07:37:17 +0000 | [diff] [blame] | 854 | QualType ElementType, | 
|  | 855 | const CXXDestructorDecl *Dtor) { | 
| David Majnemer | 0c0b6d9 | 2014-10-31 20:09:12 +0000 | [diff] [blame] | 856 | // FIXME: Provide a source location here even though there's no | 
|  | 857 | // CXXMemberCallExpr for dtor call. | 
| David Majnemer | 0868137 | 2014-11-01 07:37:17 +0000 | [diff] [blame] | 858 | bool UseGlobalDelete = DE->isGlobalDelete(); | 
| David Majnemer | 0c0b6d9 | 2014-10-31 20:09:12 +0000 | [diff] [blame] | 859 | CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting; | 
|  | 860 | llvm::Value *MDThis = | 
|  | 861 | EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, /*CE=*/nullptr); | 
|  | 862 | if (UseGlobalDelete) | 
| David Majnemer | 0868137 | 2014-11-01 07:37:17 +0000 | [diff] [blame] | 863 | CGF.EmitDeleteCall(DE->getOperatorDelete(), MDThis, ElementType); | 
| John McCall | 82fb892 | 2012-09-25 10:10:39 +0000 | [diff] [blame] | 864 | } | 
|  | 865 |  | 
| David Majnemer | 442d0a2 | 2014-11-25 07:20:20 +0000 | [diff] [blame] | 866 | void MicrosoftCXXABI::emitRethrow(CodeGenFunction &CGF, bool isNoReturn) { | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 867 | llvm::Value *Args[] = { | 
|  | 868 | llvm::ConstantPointerNull::get(CGM.Int8PtrTy), | 
|  | 869 | llvm::ConstantPointerNull::get(getThrowInfoType()->getPointerTo())}; | 
|  | 870 | auto *Fn = getThrowFn(); | 
| David Majnemer | 442d0a2 | 2014-11-25 07:20:20 +0000 | [diff] [blame] | 871 | if (isNoReturn) | 
|  | 872 | CGF.EmitNoreturnRuntimeCallOrInvoke(Fn, Args); | 
|  | 873 | else | 
|  | 874 | CGF.EmitRuntimeCallOrInvoke(Fn, Args); | 
|  | 875 | } | 
|  | 876 |  | 
| Reid Kleckner | fff8e7f | 2015-03-03 19:21:04 +0000 | [diff] [blame] | 877 | namespace { | 
| Reid Kleckner | 129552b | 2015-10-08 01:13:52 +0000 | [diff] [blame] | 878 | struct CatchRetScope final : EHScopeStack::Cleanup { | 
| David Majnemer | e888a2f | 2015-08-15 03:21:08 +0000 | [diff] [blame] | 879 | llvm::CatchPadInst *CPI; | 
|  | 880 |  | 
| Reid Kleckner | 129552b | 2015-10-08 01:13:52 +0000 | [diff] [blame] | 881 | CatchRetScope(llvm::CatchPadInst *CPI) : CPI(CPI) {} | 
| David Majnemer | e888a2f | 2015-08-15 03:21:08 +0000 | [diff] [blame] | 882 |  | 
| Reid Kleckner | fff8e7f | 2015-03-03 19:21:04 +0000 | [diff] [blame] | 883 | void Emit(CodeGenFunction &CGF, Flags flags) override { | 
| Reid Kleckner | 129552b | 2015-10-08 01:13:52 +0000 | [diff] [blame] | 884 | llvm::BasicBlock *BB = CGF.createBasicBlock("catchret.dest"); | 
|  | 885 | CGF.Builder.CreateCatchRet(CPI, BB); | 
|  | 886 | CGF.EmitBlock(BB); | 
| Reid Kleckner | fff8e7f | 2015-03-03 19:21:04 +0000 | [diff] [blame] | 887 | } | 
|  | 888 | }; | 
|  | 889 | } | 
|  | 890 |  | 
|  | 891 | void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF, | 
|  | 892 | const CXXCatchStmt *S) { | 
|  | 893 | // In the MS ABI, the runtime handles the copy, and the catch handler is | 
|  | 894 | // responsible for destruction. | 
|  | 895 | VarDecl *CatchParam = S->getExceptionDecl(); | 
| David Majnemer | 4e52d6f | 2015-12-12 05:39:21 +0000 | [diff] [blame] | 896 | llvm::BasicBlock *CatchPadBB = CGF.Builder.GetInsertBlock(); | 
| Reid Kleckner | 129552b | 2015-10-08 01:13:52 +0000 | [diff] [blame] | 897 | llvm::CatchPadInst *CPI = | 
|  | 898 | cast<llvm::CatchPadInst>(CatchPadBB->getFirstNonPHI()); | 
| David Majnemer | 4e52d6f | 2015-12-12 05:39:21 +0000 | [diff] [blame] | 899 | CGF.CurrentFuncletPad = CPI; | 
| Reid Kleckner | 129552b | 2015-10-08 01:13:52 +0000 | [diff] [blame] | 900 |  | 
| Reid Kleckner | 67cf035 | 2015-04-07 00:09:59 +0000 | [diff] [blame] | 901 | // If this is a catch-all or the catch parameter is unnamed, we don't need to | 
|  | 902 | // emit an alloca to the object. | 
|  | 903 | if (!CatchParam || !CatchParam->getDeclName()) { | 
| Reid Kleckner | 129552b | 2015-10-08 01:13:52 +0000 | [diff] [blame] | 904 | CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI); | 
| Reid Kleckner | fff8e7f | 2015-03-03 19:21:04 +0000 | [diff] [blame] | 905 | return; | 
|  | 906 | } | 
|  | 907 |  | 
|  | 908 | CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam); | 
| Reid Kleckner | 129552b | 2015-10-08 01:13:52 +0000 | [diff] [blame] | 909 | CPI->setArgOperand(2, var.getObjectAddress(CGF).getPointer()); | 
|  | 910 | CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI); | 
| Reid Kleckner | fff8e7f | 2015-03-03 19:21:04 +0000 | [diff] [blame] | 911 | CGF.EmitAutoVarCleanups(var); | 
|  | 912 | } | 
|  | 913 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 914 | /// We need to perform a generic polymorphic operation (like a typeid | 
|  | 915 | /// or a cast), which requires an object with a vfptr.  Adjust the | 
|  | 916 | /// address to point to an object with a vfptr. | 
|  | 917 | std::pair<Address, llvm::Value *> | 
|  | 918 | MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address Value, | 
| David Majnemer | 5bc883f | 2015-02-27 02:38:02 +0000 | [diff] [blame] | 919 | QualType SrcRecordTy) { | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 920 | Value = CGF.Builder.CreateBitCast(Value, CGF.Int8PtrTy); | 
|  | 921 | const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl(); | 
| David Majnemer | 9ced3dd | 2015-03-14 23:44:48 +0000 | [diff] [blame] | 922 | const ASTContext &Context = getContext(); | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 923 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 924 | // If the class itself has a vfptr, great.  This check implicitly | 
|  | 925 | // covers non-virtual base subobjects: a class with its own virtual | 
|  | 926 | // functions would be a candidate to be a primary base. | 
| David Majnemer | 5bc883f | 2015-02-27 02:38:02 +0000 | [diff] [blame] | 927 | if (Context.getASTRecordLayout(SrcDecl).hasExtendableVFPtr()) | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 928 | return std::make_pair(Value, llvm::ConstantInt::get(CGF.Int32Ty, 0)); | 
|  | 929 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 930 | // Okay, one of the vbases must have a vfptr, or else this isn't | 
|  | 931 | // actually a polymorphic class. | 
|  | 932 | const CXXRecordDecl *PolymorphicBase = nullptr; | 
|  | 933 | for (auto &Base : SrcDecl->vbases()) { | 
|  | 934 | const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); | 
|  | 935 | if (Context.getASTRecordLayout(BaseDecl).hasExtendableVFPtr()) { | 
|  | 936 | PolymorphicBase = BaseDecl; | 
|  | 937 | break; | 
|  | 938 | } | 
|  | 939 | } | 
|  | 940 | assert(PolymorphicBase && "polymorphic class has no apparent vfptr?"); | 
|  | 941 |  | 
|  | 942 | llvm::Value *Offset = | 
|  | 943 | GetVirtualBaseClassOffset(CGF, Value, SrcDecl, PolymorphicBase); | 
|  | 944 | llvm::Value *Ptr = CGF.Builder.CreateInBoundsGEP(Value.getPointer(), Offset); | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 945 | Offset = CGF.Builder.CreateTrunc(Offset, CGF.Int32Ty); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 946 | CharUnits VBaseAlign = | 
|  | 947 | CGF.CGM.getVBaseAlignment(Value.getAlignment(), SrcDecl, PolymorphicBase); | 
|  | 948 | return std::make_pair(Address(Ptr, VBaseAlign), Offset); | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 949 | } | 
|  | 950 |  | 
|  | 951 | bool MicrosoftCXXABI::shouldTypeidBeNullChecked(bool IsDeref, | 
|  | 952 | QualType SrcRecordTy) { | 
|  | 953 | const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl(); | 
|  | 954 | return IsDeref && | 
| David Majnemer | 9ced3dd | 2015-03-14 23:44:48 +0000 | [diff] [blame] | 955 | !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr(); | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 956 | } | 
|  | 957 |  | 
|  | 958 | static llvm::CallSite emitRTtypeidCall(CodeGenFunction &CGF, | 
|  | 959 | llvm::Value *Argument) { | 
|  | 960 | llvm::Type *ArgTypes[] = {CGF.Int8PtrTy}; | 
|  | 961 | llvm::FunctionType *FTy = | 
|  | 962 | llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false); | 
|  | 963 | llvm::Value *Args[] = {Argument}; | 
|  | 964 | llvm::Constant *Fn = CGF.CGM.CreateRuntimeFunction(FTy, "__RTtypeid"); | 
|  | 965 | return CGF.EmitRuntimeCallOrInvoke(Fn, Args); | 
|  | 966 | } | 
|  | 967 |  | 
|  | 968 | void MicrosoftCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) { | 
|  | 969 | llvm::CallSite Call = | 
|  | 970 | emitRTtypeidCall(CGF, llvm::Constant::getNullValue(CGM.VoidPtrTy)); | 
|  | 971 | Call.setDoesNotReturn(); | 
|  | 972 | CGF.Builder.CreateUnreachable(); | 
|  | 973 | } | 
|  | 974 |  | 
|  | 975 | llvm::Value *MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF, | 
|  | 976 | QualType SrcRecordTy, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 977 | Address ThisPtr, | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 978 | llvm::Type *StdTypeInfoPtrTy) { | 
|  | 979 | llvm::Value *Offset; | 
|  | 980 | std::tie(ThisPtr, Offset) = performBaseAdjustment(CGF, ThisPtr, SrcRecordTy); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 981 | auto Typeid = emitRTtypeidCall(CGF, ThisPtr.getPointer()).getInstruction(); | 
|  | 982 | return CGF.Builder.CreateBitCast(Typeid, StdTypeInfoPtrTy); | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 983 | } | 
|  | 984 |  | 
|  | 985 | bool MicrosoftCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr, | 
|  | 986 | QualType SrcRecordTy) { | 
|  | 987 | const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl(); | 
|  | 988 | return SrcIsPtr && | 
| David Majnemer | 9ced3dd | 2015-03-14 23:44:48 +0000 | [diff] [blame] | 989 | !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr(); | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 990 | } | 
|  | 991 |  | 
|  | 992 | llvm::Value *MicrosoftCXXABI::EmitDynamicCastCall( | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 993 | CodeGenFunction &CGF, Address This, QualType SrcRecordTy, | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 994 | QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd) { | 
|  | 995 | llvm::Type *DestLTy = CGF.ConvertType(DestTy); | 
|  | 996 |  | 
|  | 997 | llvm::Value *SrcRTTI = | 
|  | 998 | CGF.CGM.GetAddrOfRTTIDescriptor(SrcRecordTy.getUnqualifiedType()); | 
|  | 999 | llvm::Value *DestRTTI = | 
|  | 1000 | CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType()); | 
|  | 1001 |  | 
|  | 1002 | llvm::Value *Offset; | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1003 | std::tie(This, Offset) = performBaseAdjustment(CGF, This, SrcRecordTy); | 
|  | 1004 | llvm::Value *ThisPtr = This.getPointer(); | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 1005 |  | 
|  | 1006 | // PVOID __RTDynamicCast( | 
|  | 1007 | //   PVOID inptr, | 
|  | 1008 | //   LONG VfDelta, | 
|  | 1009 | //   PVOID SrcType, | 
|  | 1010 | //   PVOID TargetType, | 
|  | 1011 | //   BOOL isReference) | 
|  | 1012 | llvm::Type *ArgTypes[] = {CGF.Int8PtrTy, CGF.Int32Ty, CGF.Int8PtrTy, | 
|  | 1013 | CGF.Int8PtrTy, CGF.Int32Ty}; | 
|  | 1014 | llvm::Constant *Function = CGF.CGM.CreateRuntimeFunction( | 
|  | 1015 | llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false), | 
|  | 1016 | "__RTDynamicCast"); | 
|  | 1017 | llvm::Value *Args[] = { | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1018 | ThisPtr, Offset, SrcRTTI, DestRTTI, | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 1019 | llvm::ConstantInt::get(CGF.Int32Ty, DestTy->isReferenceType())}; | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1020 | ThisPtr = CGF.EmitRuntimeCallOrInvoke(Function, Args).getInstruction(); | 
|  | 1021 | return CGF.Builder.CreateBitCast(ThisPtr, DestLTy); | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 1022 | } | 
|  | 1023 |  | 
|  | 1024 | llvm::Value * | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1025 | MicrosoftCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF, Address Value, | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 1026 | QualType SrcRecordTy, | 
|  | 1027 | QualType DestTy) { | 
|  | 1028 | llvm::Value *Offset; | 
|  | 1029 | std::tie(Value, Offset) = performBaseAdjustment(CGF, Value, SrcRecordTy); | 
|  | 1030 |  | 
|  | 1031 | // PVOID __RTCastToVoid( | 
|  | 1032 | //   PVOID inptr) | 
|  | 1033 | llvm::Type *ArgTypes[] = {CGF.Int8PtrTy}; | 
|  | 1034 | llvm::Constant *Function = CGF.CGM.CreateRuntimeFunction( | 
|  | 1035 | llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false), | 
|  | 1036 | "__RTCastToVoid"); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1037 | llvm::Value *Args[] = {Value.getPointer()}; | 
| David Majnemer | 1162d25 | 2014-06-22 19:05:33 +0000 | [diff] [blame] | 1038 | return CGF.EmitRuntimeCall(Function, Args); | 
|  | 1039 | } | 
|  | 1040 |  | 
|  | 1041 | bool MicrosoftCXXABI::EmitBadCastCall(CodeGenFunction &CGF) { | 
|  | 1042 | return false; | 
|  | 1043 | } | 
|  | 1044 |  | 
| David Majnemer | ca32f93 | 2014-09-01 18:50:02 +0000 | [diff] [blame] | 1045 | llvm::Value *MicrosoftCXXABI::GetVirtualBaseClassOffset( | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1046 | CodeGenFunction &CGF, Address This, const CXXRecordDecl *ClassDecl, | 
| David Majnemer | ca32f93 | 2014-09-01 18:50:02 +0000 | [diff] [blame] | 1047 | const CXXRecordDecl *BaseClassDecl) { | 
| David Majnemer | 9ced3dd | 2015-03-14 23:44:48 +0000 | [diff] [blame] | 1048 | const ASTContext &Context = getContext(); | 
| Reid Kleckner | 5b1b5d5 | 2014-01-14 00:50:39 +0000 | [diff] [blame] | 1049 | int64_t VBPtrChars = | 
| David Majnemer | 9ced3dd | 2015-03-14 23:44:48 +0000 | [diff] [blame] | 1050 | Context.getASTRecordLayout(ClassDecl).getVBPtrOffset().getQuantity(); | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 1051 | llvm::Value *VBPtrOffset = llvm::ConstantInt::get(CGM.PtrDiffTy, VBPtrChars); | 
| David Majnemer | 9ced3dd | 2015-03-14 23:44:48 +0000 | [diff] [blame] | 1052 | CharUnits IntSize = Context.getTypeSizeInChars(Context.IntTy); | 
| Timur Iskhodzhanov | 5877663 | 2013-11-05 15:54:58 +0000 | [diff] [blame] | 1053 | CharUnits VBTableChars = | 
|  | 1054 | IntSize * | 
|  | 1055 | CGM.getMicrosoftVTableContext().getVBTableIndex(ClassDecl, BaseClassDecl); | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 1056 | llvm::Value *VBTableOffset = | 
| David Majnemer | ca32f93 | 2014-09-01 18:50:02 +0000 | [diff] [blame] | 1057 | llvm::ConstantInt::get(CGM.IntTy, VBTableChars.getQuantity()); | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 1058 |  | 
|  | 1059 | llvm::Value *VBPtrToNewBase = | 
| David Majnemer | ca32f93 | 2014-09-01 18:50:02 +0000 | [diff] [blame] | 1060 | GetVBaseOffsetFromVBPtr(CGF, This, VBPtrOffset, VBTableOffset); | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 1061 | VBPtrToNewBase = | 
| David Majnemer | ca32f93 | 2014-09-01 18:50:02 +0000 | [diff] [blame] | 1062 | CGF.Builder.CreateSExtOrBitCast(VBPtrToNewBase, CGM.PtrDiffTy); | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 1063 | return CGF.Builder.CreateNSWAdd(VBPtrOffset, VBPtrToNewBase); | 
|  | 1064 | } | 
|  | 1065 |  | 
| Stephen Lin | 9dc6eef | 2013-06-30 20:40:16 +0000 | [diff] [blame] | 1066 | bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD) const { | 
|  | 1067 | return isa<CXXConstructorDecl>(GD.getDecl()); | 
| John McCall | 0f999f3 | 2012-09-25 08:00:39 +0000 | [diff] [blame] | 1068 | } | 
|  | 1069 |  | 
| David Majnemer | 0c0b6d9 | 2014-10-31 20:09:12 +0000 | [diff] [blame] | 1070 | static bool isDeletingDtor(GlobalDecl GD) { | 
|  | 1071 | return isa<CXXDestructorDecl>(GD.getDecl()) && | 
|  | 1072 | GD.getDtorType() == Dtor_Deleting; | 
|  | 1073 | } | 
|  | 1074 |  | 
|  | 1075 | bool MicrosoftCXXABI::hasMostDerivedReturn(GlobalDecl GD) const { | 
|  | 1076 | return isDeletingDtor(GD); | 
|  | 1077 | } | 
|  | 1078 |  | 
| Reid Kleckner | 40ca913 | 2014-05-13 22:05:45 +0000 | [diff] [blame] | 1079 | bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI) const { | 
|  | 1080 | const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl(); | 
|  | 1081 | if (!RD) | 
|  | 1082 | return false; | 
|  | 1083 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1084 | CharUnits Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType()); | 
| Reid Kleckner | 40ca913 | 2014-05-13 22:05:45 +0000 | [diff] [blame] | 1085 | if (FI.isInstanceMethod()) { | 
|  | 1086 | // If it's an instance method, aggregates are always returned indirectly via | 
|  | 1087 | // the second parameter. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1088 | FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false); | 
| Reid Kleckner | 40ca913 | 2014-05-13 22:05:45 +0000 | [diff] [blame] | 1089 | FI.getReturnInfo().setSRetAfterThis(FI.isInstanceMethod()); | 
|  | 1090 | return true; | 
|  | 1091 | } else if (!RD->isPOD()) { | 
|  | 1092 | // If it's a free function, non-POD types are returned indirectly. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1093 | FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false); | 
| Reid Kleckner | 40ca913 | 2014-05-13 22:05:45 +0000 | [diff] [blame] | 1094 | return true; | 
|  | 1095 | } | 
|  | 1096 |  | 
|  | 1097 | // Otherwise, use the C ABI rules. | 
|  | 1098 | return false; | 
|  | 1099 | } | 
|  | 1100 |  | 
| Reid Kleckner | 7810af0 | 2013-06-19 15:20:38 +0000 | [diff] [blame] | 1101 | llvm::BasicBlock * | 
|  | 1102 | MicrosoftCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, | 
|  | 1103 | const CXXRecordDecl *RD) { | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1104 | llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF); | 
|  | 1105 | assert(IsMostDerivedClass && | 
|  | 1106 | "ctor for a class with virtual bases must have an implicit parameter"); | 
| Reid Kleckner | 7810af0 | 2013-06-19 15:20:38 +0000 | [diff] [blame] | 1107 | llvm::Value *IsCompleteObject = | 
|  | 1108 | CGF.Builder.CreateIsNotNull(IsMostDerivedClass, "is_complete_object"); | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1109 |  | 
|  | 1110 | llvm::BasicBlock *CallVbaseCtorsBB = CGF.createBasicBlock("ctor.init_vbases"); | 
|  | 1111 | llvm::BasicBlock *SkipVbaseCtorsBB = CGF.createBasicBlock("ctor.skip_vbases"); | 
|  | 1112 | CGF.Builder.CreateCondBr(IsCompleteObject, | 
|  | 1113 | CallVbaseCtorsBB, SkipVbaseCtorsBB); | 
|  | 1114 |  | 
|  | 1115 | CGF.EmitBlock(CallVbaseCtorsBB); | 
| Reid Kleckner | 7810af0 | 2013-06-19 15:20:38 +0000 | [diff] [blame] | 1116 |  | 
|  | 1117 | // Fill in the vbtable pointers here. | 
|  | 1118 | EmitVBPtrStores(CGF, RD); | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1119 |  | 
|  | 1120 | // CGF will put the base ctor calls in this basic block for us later. | 
|  | 1121 |  | 
|  | 1122 | return SkipVbaseCtorsBB; | 
| John McCall | 0f999f3 | 2012-09-25 08:00:39 +0000 | [diff] [blame] | 1123 | } | 
|  | 1124 |  | 
| Timur Iskhodzhanov | b648732 | 2013-10-09 18:16:58 +0000 | [diff] [blame] | 1125 | void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers( | 
|  | 1126 | CodeGenFunction &CGF, const CXXRecordDecl *RD) { | 
|  | 1127 | // In most cases, an override for a vbase virtual method can adjust | 
|  | 1128 | // the "this" parameter by applying a constant offset. | 
|  | 1129 | // However, this is not enough while a constructor or a destructor of some | 
|  | 1130 | // class X is being executed if all the following conditions are met: | 
|  | 1131 | //  - X has virtual bases, (1) | 
|  | 1132 | //  - X overrides a virtual method M of a vbase Y, (2) | 
|  | 1133 | //  - X itself is a vbase of the most derived class. | 
|  | 1134 | // | 
|  | 1135 | // If (1) and (2) are true, the vtorDisp for vbase Y is a hidden member of X | 
|  | 1136 | // which holds the extra amount of "this" adjustment we must do when we use | 
|  | 1137 | // the X vftables (i.e. during X ctor or dtor). | 
|  | 1138 | // Outside the ctors and dtors, the values of vtorDisps are zero. | 
|  | 1139 |  | 
|  | 1140 | const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); | 
|  | 1141 | typedef ASTRecordLayout::VBaseOffsetsMapTy VBOffsets; | 
|  | 1142 | const VBOffsets &VBaseMap = Layout.getVBaseOffsetsMap(); | 
|  | 1143 | CGBuilderTy &Builder = CGF.Builder; | 
|  | 1144 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1145 | unsigned AS = getThisAddress(CGF).getAddressSpace(); | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1146 | llvm::Value *Int8This = nullptr;  // Initialize lazily. | 
| Timur Iskhodzhanov | b648732 | 2013-10-09 18:16:58 +0000 | [diff] [blame] | 1147 |  | 
|  | 1148 | for (VBOffsets::const_iterator I = VBaseMap.begin(), E = VBaseMap.end(); | 
|  | 1149 | I != E; ++I) { | 
|  | 1150 | if (!I->second.hasVtorDisp()) | 
|  | 1151 | continue; | 
|  | 1152 |  | 
| Timur Iskhodzhanov | 4ddf592 | 2013-11-13 16:03:43 +0000 | [diff] [blame] | 1153 | llvm::Value *VBaseOffset = | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1154 | GetVirtualBaseClassOffset(CGF, getThisAddress(CGF), RD, I->first); | 
| Timur Iskhodzhanov | b648732 | 2013-10-09 18:16:58 +0000 | [diff] [blame] | 1155 | // FIXME: it doesn't look right that we SExt in GetVirtualBaseClassOffset() | 
|  | 1156 | // just to Trunc back immediately. | 
|  | 1157 | VBaseOffset = Builder.CreateTruncOrBitCast(VBaseOffset, CGF.Int32Ty); | 
|  | 1158 | uint64_t ConstantVBaseOffset = | 
|  | 1159 | Layout.getVBaseClassOffset(I->first).getQuantity(); | 
|  | 1160 |  | 
|  | 1161 | // vtorDisp_for_vbase = vbptr[vbase_idx] - offsetof(RD, vbase). | 
|  | 1162 | llvm::Value *VtorDispValue = Builder.CreateSub( | 
|  | 1163 | VBaseOffset, llvm::ConstantInt::get(CGM.Int32Ty, ConstantVBaseOffset), | 
|  | 1164 | "vtordisp.value"); | 
|  | 1165 |  | 
|  | 1166 | if (!Int8This) | 
|  | 1167 | Int8This = Builder.CreateBitCast(getThisValue(CGF), | 
|  | 1168 | CGF.Int8Ty->getPointerTo(AS)); | 
|  | 1169 | llvm::Value *VtorDispPtr = Builder.CreateInBoundsGEP(Int8This, VBaseOffset); | 
|  | 1170 | // vtorDisp is always the 32-bits before the vbase in the class layout. | 
|  | 1171 | VtorDispPtr = Builder.CreateConstGEP1_32(VtorDispPtr, -4); | 
|  | 1172 | VtorDispPtr = Builder.CreateBitCast( | 
|  | 1173 | VtorDispPtr, CGF.Int32Ty->getPointerTo(AS), "vtordisp.ptr"); | 
|  | 1174 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1175 | Builder.CreateAlignedStore(VtorDispValue, VtorDispPtr, | 
|  | 1176 | CharUnits::fromQuantity(4)); | 
| Timur Iskhodzhanov | b648732 | 2013-10-09 18:16:58 +0000 | [diff] [blame] | 1177 | } | 
|  | 1178 | } | 
|  | 1179 |  | 
| David Majnemer | 37fd66e | 2015-03-13 22:36:55 +0000 | [diff] [blame] | 1180 | static bool hasDefaultCXXMethodCC(ASTContext &Context, | 
|  | 1181 | const CXXMethodDecl *MD) { | 
|  | 1182 | CallingConv ExpectedCallingConv = Context.getDefaultCallingConvention( | 
|  | 1183 | /*IsVariadic=*/false, /*IsCXXMethod=*/true); | 
|  | 1184 | CallingConv ActualCallingConv = | 
|  | 1185 | MD->getType()->getAs<FunctionProtoType>()->getCallConv(); | 
|  | 1186 | return ExpectedCallingConv == ActualCallingConv; | 
|  | 1187 | } | 
|  | 1188 |  | 
| Timur Iskhodzhanov | 40f2fa9 | 2013-08-04 17:30:04 +0000 | [diff] [blame] | 1189 | void MicrosoftCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) { | 
|  | 1190 | // There's only one constructor type in this ABI. | 
|  | 1191 | CGM.EmitGlobal(GlobalDecl(D, Ctor_Complete)); | 
| David Majnemer | 37fd66e | 2015-03-13 22:36:55 +0000 | [diff] [blame] | 1192 |  | 
|  | 1193 | // Exported default constructors either have a simple call-site where they use | 
|  | 1194 | // the typical calling convention and have a single 'this' pointer for an | 
|  | 1195 | // argument -or- they get a wrapper function which appropriately thunks to the | 
|  | 1196 | // real default constructor.  This thunk is the default constructor closure. | 
|  | 1197 | if (D->hasAttr<DLLExportAttr>() && D->isDefaultConstructor()) | 
|  | 1198 | if (!hasDefaultCXXMethodCC(getContext(), D) || D->getNumParams() != 0) { | 
|  | 1199 | llvm::Function *Fn = getAddrOfCXXCtorClosure(D, Ctor_DefaultClosure); | 
|  | 1200 | Fn->setLinkage(llvm::GlobalValue::WeakODRLinkage); | 
|  | 1201 | Fn->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); | 
|  | 1202 | } | 
| Timur Iskhodzhanov | 40f2fa9 | 2013-08-04 17:30:04 +0000 | [diff] [blame] | 1203 | } | 
|  | 1204 |  | 
| Reid Kleckner | 7810af0 | 2013-06-19 15:20:38 +0000 | [diff] [blame] | 1205 | void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF, | 
|  | 1206 | const CXXRecordDecl *RD) { | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1207 | Address This = getThisAddress(CGF); | 
|  | 1208 | This = CGF.Builder.CreateElementBitCast(This, CGM.Int8Ty, "this.int8"); | 
| David Majnemer | 9ced3dd | 2015-03-14 23:44:48 +0000 | [diff] [blame] | 1209 | const ASTContext &Context = getContext(); | 
|  | 1210 | const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); | 
| Reid Kleckner | 7810af0 | 2013-06-19 15:20:38 +0000 | [diff] [blame] | 1211 |  | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 1212 | const VBTableGlobals &VBGlobals = enumerateVBTables(RD); | 
|  | 1213 | for (unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) { | 
| Reid Kleckner | 9c6e9e3 | 2014-02-27 19:40:09 +0000 | [diff] [blame] | 1214 | const VPtrInfo *VBT = (*VBGlobals.VBTables)[I]; | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 1215 | llvm::GlobalVariable *GV = VBGlobals.Globals[I]; | 
| Reid Kleckner | 7810af0 | 2013-06-19 15:20:38 +0000 | [diff] [blame] | 1216 | const ASTRecordLayout &SubobjectLayout = | 
| David Majnemer | 9ced3dd | 2015-03-14 23:44:48 +0000 | [diff] [blame] | 1217 | Context.getASTRecordLayout(VBT->BaseWithVPtr); | 
| Reid Kleckner | 5f08094 | 2014-01-03 23:42:00 +0000 | [diff] [blame] | 1218 | CharUnits Offs = VBT->NonVirtualOffset; | 
|  | 1219 | Offs += SubobjectLayout.getVBPtrOffset(); | 
| Reid Kleckner | 9c6e9e3 | 2014-02-27 19:40:09 +0000 | [diff] [blame] | 1220 | if (VBT->getVBaseWithVPtr()) | 
|  | 1221 | Offs += Layout.getVBaseClassOffset(VBT->getVBaseWithVPtr()); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1222 | Address VBPtr = CGF.Builder.CreateConstInBoundsByteGEP(This, Offs); | 
| David Blaikie | 1ed728c | 2015-04-05 22:45:47 +0000 | [diff] [blame] | 1223 | llvm::Value *GVPtr = | 
|  | 1224 | CGF.Builder.CreateConstInBoundsGEP2_32(GV->getValueType(), GV, 0, 0); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1225 | VBPtr = CGF.Builder.CreateElementBitCast(VBPtr, GVPtr->getType(), | 
| Reid Kleckner | 5f08094 | 2014-01-03 23:42:00 +0000 | [diff] [blame] | 1226 | "vbptr." + VBT->ReusingBase->getName()); | 
| Reid Kleckner | 0ba8ba4 | 2014-10-22 17:26:00 +0000 | [diff] [blame] | 1227 | CGF.Builder.CreateStore(GVPtr, VBPtr); | 
| Reid Kleckner | 7810af0 | 2013-06-19 15:20:38 +0000 | [diff] [blame] | 1228 | } | 
|  | 1229 | } | 
|  | 1230 |  | 
| Rafael Espindola | 8d2a19b | 2014-09-08 16:01:27 +0000 | [diff] [blame] | 1231 | void | 
|  | 1232 | MicrosoftCXXABI::buildStructorSignature(const CXXMethodDecl *MD, StructorType T, | 
| Timur Iskhodzhanov | ee6bc53 | 2013-02-13 08:37:51 +0000 | [diff] [blame] | 1233 | SmallVectorImpl<CanQualType> &ArgTys) { | 
| Timur Iskhodzhanov | ee6bc53 | 2013-02-13 08:37:51 +0000 | [diff] [blame] | 1234 | // TODO: 'for base' flag | 
| Rafael Espindola | 8d2a19b | 2014-09-08 16:01:27 +0000 | [diff] [blame] | 1235 | if (T == StructorType::Deleting) { | 
| Timur Iskhodzhanov | 701981f | 2013-08-27 10:38:19 +0000 | [diff] [blame] | 1236 | // The scalar deleting destructor takes an implicit int parameter. | 
| David Majnemer | 9ced3dd | 2015-03-14 23:44:48 +0000 | [diff] [blame] | 1237 | ArgTys.push_back(getContext().IntTy); | 
| Timur Iskhodzhanov | ee6bc53 | 2013-02-13 08:37:51 +0000 | [diff] [blame] | 1238 | } | 
| Rafael Espindola | 8d2a19b | 2014-09-08 16:01:27 +0000 | [diff] [blame] | 1239 | auto *CD = dyn_cast<CXXConstructorDecl>(MD); | 
|  | 1240 | if (!CD) | 
|  | 1241 | return; | 
|  | 1242 |  | 
|  | 1243 | // All parameters are already in place except is_most_derived, which goes | 
|  | 1244 | // after 'this' if it's variadic and last if it's not. | 
|  | 1245 |  | 
|  | 1246 | const CXXRecordDecl *Class = CD->getParent(); | 
|  | 1247 | const FunctionProtoType *FPT = CD->getType()->castAs<FunctionProtoType>(); | 
|  | 1248 | if (Class->getNumVBases()) { | 
|  | 1249 | if (FPT->isVariadic()) | 
| David Majnemer | 9ced3dd | 2015-03-14 23:44:48 +0000 | [diff] [blame] | 1250 | ArgTys.insert(ArgTys.begin() + 1, getContext().IntTy); | 
| Rafael Espindola | 8d2a19b | 2014-09-08 16:01:27 +0000 | [diff] [blame] | 1251 | else | 
| David Majnemer | 9ced3dd | 2015-03-14 23:44:48 +0000 | [diff] [blame] | 1252 | ArgTys.push_back(getContext().IntTy); | 
| Rafael Espindola | 8d2a19b | 2014-09-08 16:01:27 +0000 | [diff] [blame] | 1253 | } | 
| Timur Iskhodzhanov | ee6bc53 | 2013-02-13 08:37:51 +0000 | [diff] [blame] | 1254 | } | 
|  | 1255 |  | 
| Reid Kleckner | e7de47e | 2013-07-22 13:51:44 +0000 | [diff] [blame] | 1256 | void MicrosoftCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) { | 
|  | 1257 | // The TU defining a dtor is only guaranteed to emit a base destructor.  All | 
|  | 1258 | // other destructor variants are delegating thunks. | 
|  | 1259 | CGM.EmitGlobal(GlobalDecl(D, Dtor_Base)); | 
|  | 1260 | } | 
|  | 1261 |  | 
| Timur Iskhodzhanov | f174942 | 2014-03-14 17:43:37 +0000 | [diff] [blame] | 1262 | CharUnits | 
|  | 1263 | MicrosoftCXXABI::getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD) { | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 1264 | GD = GD.getCanonicalDecl(); | 
|  | 1265 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); | 
| Timur Iskhodzhanov | f174942 | 2014-03-14 17:43:37 +0000 | [diff] [blame] | 1266 |  | 
|  | 1267 | GlobalDecl LookupGD = GD; | 
|  | 1268 | if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { | 
|  | 1269 | // Complete destructors take a pointer to the complete object as a | 
|  | 1270 | // parameter, thus don't need this adjustment. | 
|  | 1271 | if (GD.getDtorType() == Dtor_Complete) | 
|  | 1272 | return CharUnits(); | 
|  | 1273 |  | 
|  | 1274 | // There's no Dtor_Base in vftable but it shares the this adjustment with | 
|  | 1275 | // the deleting one, so look it up instead. | 
|  | 1276 | LookupGD = GlobalDecl(DD, Dtor_Deleting); | 
|  | 1277 | } | 
|  | 1278 |  | 
|  | 1279 | MicrosoftVTableContext::MethodVFTableLocation ML = | 
|  | 1280 | CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD); | 
|  | 1281 | CharUnits Adjustment = ML.VFPtrOffset; | 
|  | 1282 |  | 
|  | 1283 | // Normal virtual instance methods need to adjust from the vfptr that first | 
|  | 1284 | // defined the virtual method to the virtual base subobject, but destructors | 
|  | 1285 | // do not.  The vector deleting destructor thunk applies this adjustment for | 
|  | 1286 | // us if necessary. | 
|  | 1287 | if (isa<CXXDestructorDecl>(MD)) | 
|  | 1288 | Adjustment = CharUnits::Zero(); | 
|  | 1289 |  | 
|  | 1290 | if (ML.VBase) { | 
|  | 1291 | const ASTRecordLayout &DerivedLayout = | 
| David Majnemer | 9ced3dd | 2015-03-14 23:44:48 +0000 | [diff] [blame] | 1292 | getContext().getASTRecordLayout(MD->getParent()); | 
| Timur Iskhodzhanov | f174942 | 2014-03-14 17:43:37 +0000 | [diff] [blame] | 1293 | Adjustment += DerivedLayout.getVBaseClassOffset(ML.VBase); | 
|  | 1294 | } | 
|  | 1295 |  | 
|  | 1296 | return Adjustment; | 
|  | 1297 | } | 
|  | 1298 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1299 | Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall( | 
|  | 1300 | CodeGenFunction &CGF, GlobalDecl GD, Address This, | 
|  | 1301 | bool VirtualCall) { | 
| Timur Iskhodzhanov | f174942 | 2014-03-14 17:43:37 +0000 | [diff] [blame] | 1302 | if (!VirtualCall) { | 
|  | 1303 | // If the call of a virtual function is not virtual, we just have to | 
|  | 1304 | // compensate for the adjustment the virtual function does in its prologue. | 
|  | 1305 | CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(GD); | 
|  | 1306 | if (Adjustment.isZero()) | 
|  | 1307 | return This; | 
|  | 1308 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1309 | This = CGF.Builder.CreateElementBitCast(This, CGF.Int8Ty); | 
| Timur Iskhodzhanov | f174942 | 2014-03-14 17:43:37 +0000 | [diff] [blame] | 1310 | assert(Adjustment.isPositive()); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1311 | return CGF.Builder.CreateConstByteGEP(This, Adjustment); | 
| Timur Iskhodzhanov | f174942 | 2014-03-14 17:43:37 +0000 | [diff] [blame] | 1312 | } | 
|  | 1313 |  | 
|  | 1314 | GD = GD.getCanonicalDecl(); | 
|  | 1315 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 1316 |  | 
| Timur Iskhodzhanov | 62082b7 | 2013-10-16 18:24:06 +0000 | [diff] [blame] | 1317 | GlobalDecl LookupGD = GD; | 
|  | 1318 | if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { | 
|  | 1319 | // Complete dtors take a pointer to the complete object, | 
|  | 1320 | // thus don't need adjustment. | 
|  | 1321 | if (GD.getDtorType() == Dtor_Complete) | 
|  | 1322 | return This; | 
|  | 1323 |  | 
|  | 1324 | // There's only Dtor_Deleting in vftable but it shares the this adjustment | 
|  | 1325 | // with the base one, so look up the deleting one instead. | 
|  | 1326 | LookupGD = GlobalDecl(DD, Dtor_Deleting); | 
|  | 1327 | } | 
| Timur Iskhodzhanov | 5877663 | 2013-11-05 15:54:58 +0000 | [diff] [blame] | 1328 | MicrosoftVTableContext::MethodVFTableLocation ML = | 
|  | 1329 | CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD); | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 1330 |  | 
| Timur Iskhodzhanov | 9e7f505 | 2013-11-07 13:34:02 +0000 | [diff] [blame] | 1331 | CharUnits StaticOffset = ML.VFPtrOffset; | 
| Reid Kleckner | 0c12b36 | 2014-02-18 22:51:52 +0000 | [diff] [blame] | 1332 |  | 
|  | 1333 | // Base destructors expect 'this' to point to the beginning of the base | 
|  | 1334 | // subobject, not the first vfptr that happens to contain the virtual dtor. | 
|  | 1335 | // However, we still need to apply the virtual base adjustment. | 
|  | 1336 | if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base) | 
|  | 1337 | StaticOffset = CharUnits::Zero(); | 
|  | 1338 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1339 | Address Result = This; | 
| Timur Iskhodzhanov | 62082b7 | 2013-10-16 18:24:06 +0000 | [diff] [blame] | 1340 | if (ML.VBase) { | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1341 | Result = CGF.Builder.CreateElementBitCast(Result, CGF.Int8Ty); | 
|  | 1342 |  | 
|  | 1343 | const CXXRecordDecl *Derived = MD->getParent(); | 
|  | 1344 | const CXXRecordDecl *VBase = ML.VBase; | 
| Timur Iskhodzhanov | f174942 | 2014-03-14 17:43:37 +0000 | [diff] [blame] | 1345 | llvm::Value *VBaseOffset = | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1346 | GetVirtualBaseClassOffset(CGF, Result, Derived, VBase); | 
|  | 1347 | llvm::Value *VBasePtr = | 
|  | 1348 | CGF.Builder.CreateInBoundsGEP(Result.getPointer(), VBaseOffset); | 
|  | 1349 | CharUnits VBaseAlign = | 
|  | 1350 | CGF.CGM.getVBaseAlignment(Result.getAlignment(), Derived, VBase); | 
|  | 1351 | Result = Address(VBasePtr, VBaseAlign); | 
| Timur Iskhodzhanov | 62082b7 | 2013-10-16 18:24:06 +0000 | [diff] [blame] | 1352 | } | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 1353 | if (!StaticOffset.isZero()) { | 
|  | 1354 | assert(StaticOffset.isPositive()); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1355 | Result = CGF.Builder.CreateElementBitCast(Result, CGF.Int8Ty); | 
| Timur Iskhodzhanov | 827365e | 2013-10-22 18:15:24 +0000 | [diff] [blame] | 1356 | if (ML.VBase) { | 
|  | 1357 | // Non-virtual adjustment might result in a pointer outside the allocated | 
|  | 1358 | // object, e.g. if the final overrider class is laid out after the virtual | 
|  | 1359 | // base that declares a method in the most derived class. | 
|  | 1360 | // FIXME: Update the code that emits this adjustment in thunks prologues. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1361 | Result = CGF.Builder.CreateConstByteGEP(Result, StaticOffset); | 
| Timur Iskhodzhanov | 827365e | 2013-10-22 18:15:24 +0000 | [diff] [blame] | 1362 | } else { | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1363 | Result = CGF.Builder.CreateConstInBoundsByteGEP(Result, StaticOffset); | 
| Timur Iskhodzhanov | 827365e | 2013-10-22 18:15:24 +0000 | [diff] [blame] | 1364 | } | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 1365 | } | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1366 | return Result; | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 1367 | } | 
|  | 1368 |  | 
| Reid Kleckner | 89077a1 | 2013-12-17 19:46:40 +0000 | [diff] [blame] | 1369 | void MicrosoftCXXABI::addImplicitStructorParams(CodeGenFunction &CGF, | 
|  | 1370 | QualType &ResTy, | 
|  | 1371 | FunctionArgList &Params) { | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1372 | ASTContext &Context = getContext(); | 
|  | 1373 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); | 
| Reid Kleckner | 89077a1 | 2013-12-17 19:46:40 +0000 | [diff] [blame] | 1374 | assert(isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)); | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1375 | if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) { | 
|  | 1376 | ImplicitParamDecl *IsMostDerived | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1377 | = ImplicitParamDecl::Create(Context, nullptr, | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1378 | CGF.CurGD.getDecl()->getLocation(), | 
|  | 1379 | &Context.Idents.get("is_most_derived"), | 
|  | 1380 | Context.IntTy); | 
| Reid Kleckner | 89077a1 | 2013-12-17 19:46:40 +0000 | [diff] [blame] | 1381 | // The 'most_derived' parameter goes second if the ctor is variadic and last | 
|  | 1382 | // if it's not.  Dtors can't be variadic. | 
|  | 1383 | const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); | 
|  | 1384 | if (FPT->isVariadic()) | 
|  | 1385 | Params.insert(Params.begin() + 1, IsMostDerived); | 
|  | 1386 | else | 
|  | 1387 | Params.push_back(IsMostDerived); | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1388 | getStructorImplicitParamDecl(CGF) = IsMostDerived; | 
| David Majnemer | 0c0b6d9 | 2014-10-31 20:09:12 +0000 | [diff] [blame] | 1389 | } else if (isDeletingDtor(CGF.CurGD)) { | 
| Timur Iskhodzhanov | ee6bc53 | 2013-02-13 08:37:51 +0000 | [diff] [blame] | 1390 | ImplicitParamDecl *ShouldDelete | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1391 | = ImplicitParamDecl::Create(Context, nullptr, | 
| Timur Iskhodzhanov | ee6bc53 | 2013-02-13 08:37:51 +0000 | [diff] [blame] | 1392 | CGF.CurGD.getDecl()->getLocation(), | 
|  | 1393 | &Context.Idents.get("should_call_delete"), | 
| Timur Iskhodzhanov | 701981f | 2013-08-27 10:38:19 +0000 | [diff] [blame] | 1394 | Context.IntTy); | 
| Timur Iskhodzhanov | ee6bc53 | 2013-02-13 08:37:51 +0000 | [diff] [blame] | 1395 | Params.push_back(ShouldDelete); | 
|  | 1396 | getStructorImplicitParamDecl(CGF) = ShouldDelete; | 
|  | 1397 | } | 
| John McCall | 0f999f3 | 2012-09-25 08:00:39 +0000 | [diff] [blame] | 1398 | } | 
|  | 1399 |  | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 1400 | llvm::Value *MicrosoftCXXABI::adjustThisParameterInVirtualFunctionPrologue( | 
|  | 1401 | CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This) { | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 1402 | // In this ABI, every virtual function takes a pointer to one of the | 
|  | 1403 | // subobjects that first defines it as the 'this' parameter, rather than a | 
| Alp Toker | f6a24ce | 2013-12-05 16:25:25 +0000 | [diff] [blame] | 1404 | // pointer to the final overrider subobject. Thus, we need to adjust it back | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 1405 | // to the final overrider subobject before use. | 
|  | 1406 | // See comments in the MicrosoftVFTableContext implementation for the details. | 
| Timur Iskhodzhanov | f174942 | 2014-03-14 17:43:37 +0000 | [diff] [blame] | 1407 | CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(GD); | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 1408 | if (Adjustment.isZero()) | 
|  | 1409 | return This; | 
|  | 1410 |  | 
|  | 1411 | unsigned AS = cast<llvm::PointerType>(This->getType())->getAddressSpace(); | 
|  | 1412 | llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS), | 
|  | 1413 | *thisTy = This->getType(); | 
|  | 1414 |  | 
|  | 1415 | This = CGF.Builder.CreateBitCast(This, charPtrTy); | 
|  | 1416 | assert(Adjustment.isPositive()); | 
| David Blaikie | fb901c7a | 2015-04-04 15:12:29 +0000 | [diff] [blame] | 1417 | This = CGF.Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, This, | 
|  | 1418 | -Adjustment.getQuantity()); | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 1419 | return CGF.Builder.CreateBitCast(This, thisTy); | 
|  | 1420 | } | 
|  | 1421 |  | 
| John McCall | 0f999f3 | 2012-09-25 08:00:39 +0000 | [diff] [blame] | 1422 | void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { | 
|  | 1423 | EmitThisParam(CGF); | 
| Stephen Lin | 9dc6eef | 2013-06-30 20:40:16 +0000 | [diff] [blame] | 1424 |  | 
|  | 1425 | /// If this is a function that the ABI specifies returns 'this', initialize | 
|  | 1426 | /// the return slot to 'this' at the start of the function. | 
|  | 1427 | /// | 
|  | 1428 | /// Unlike the setting of return types, this is done within the ABI | 
|  | 1429 | /// implementation instead of by clients of CGCXXABI because: | 
|  | 1430 | /// 1) getThisValue is currently protected | 
|  | 1431 | /// 2) in theory, an ABI could implement 'this' returns some other way; | 
|  | 1432 | ///    HasThisReturn only specifies a contract, not the implementation | 
|  | 1433 | if (HasThisReturn(CGF.CurGD)) | 
| John McCall | 0f999f3 | 2012-09-25 08:00:39 +0000 | [diff] [blame] | 1434 | CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue); | 
| David Majnemer | 0c0b6d9 | 2014-10-31 20:09:12 +0000 | [diff] [blame] | 1435 | else if (hasMostDerivedReturn(CGF.CurGD)) | 
|  | 1436 | CGF.Builder.CreateStore(CGF.EmitCastToVoidPtr(getThisValue(CGF)), | 
|  | 1437 | CGF.ReturnValue); | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1438 |  | 
|  | 1439 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); | 
|  | 1440 | if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) { | 
|  | 1441 | assert(getStructorImplicitParamDecl(CGF) && | 
|  | 1442 | "no implicit parameter for a constructor with virtual bases?"); | 
|  | 1443 | getStructorImplicitParamValue(CGF) | 
|  | 1444 | = CGF.Builder.CreateLoad( | 
|  | 1445 | CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)), | 
|  | 1446 | "is_most_derived"); | 
|  | 1447 | } | 
|  | 1448 |  | 
| David Majnemer | 0c0b6d9 | 2014-10-31 20:09:12 +0000 | [diff] [blame] | 1449 | if (isDeletingDtor(CGF.CurGD)) { | 
| Timur Iskhodzhanov | ee6bc53 | 2013-02-13 08:37:51 +0000 | [diff] [blame] | 1450 | assert(getStructorImplicitParamDecl(CGF) && | 
|  | 1451 | "no implicit parameter for a deleting destructor?"); | 
|  | 1452 | getStructorImplicitParamValue(CGF) | 
|  | 1453 | = CGF.Builder.CreateLoad( | 
|  | 1454 | CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)), | 
|  | 1455 | "should_call_delete"); | 
|  | 1456 | } | 
| John McCall | 0f999f3 | 2012-09-25 08:00:39 +0000 | [diff] [blame] | 1457 | } | 
|  | 1458 |  | 
| Reid Kleckner | 89077a1 | 2013-12-17 19:46:40 +0000 | [diff] [blame] | 1459 | unsigned MicrosoftCXXABI::addImplicitConstructorArgs( | 
|  | 1460 | CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type, | 
|  | 1461 | bool ForVirtualBase, bool Delegating, CallArgList &Args) { | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1462 | assert(Type == Ctor_Complete || Type == Ctor_Base); | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1463 |  | 
| Reid Kleckner | 89077a1 | 2013-12-17 19:46:40 +0000 | [diff] [blame] | 1464 | // Check if we need a 'most_derived' parameter. | 
|  | 1465 | if (!D->getParent()->getNumVBases()) | 
|  | 1466 | return 0; | 
|  | 1467 |  | 
|  | 1468 | // Add the 'most_derived' argument second if we are variadic or last if not. | 
|  | 1469 | const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>(); | 
| David Majnemer | 833b91e | 2016-05-13 20:05:09 +0000 | [diff] [blame] | 1470 | llvm::Value *MostDerivedArg; | 
|  | 1471 | if (Delegating) { | 
|  | 1472 | MostDerivedArg = getStructorImplicitParamValue(CGF); | 
|  | 1473 | } else { | 
|  | 1474 | MostDerivedArg = llvm::ConstantInt::get(CGM.Int32Ty, Type == Ctor_Complete); | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1475 | } | 
| David Majnemer | 833b91e | 2016-05-13 20:05:09 +0000 | [diff] [blame] | 1476 | RValue RV = RValue::get(MostDerivedArg); | 
|  | 1477 | if (FPT->isVariadic()) | 
|  | 1478 | Args.insert(Args.begin() + 1, | 
|  | 1479 | CallArg(RV, getContext().IntTy, /*needscopy=*/false)); | 
|  | 1480 | else | 
|  | 1481 | Args.add(RV, getContext().IntTy); | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1482 |  | 
| Reid Kleckner | 89077a1 | 2013-12-17 19:46:40 +0000 | [diff] [blame] | 1483 | return 1;  // Added one arg. | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1484 | } | 
|  | 1485 |  | 
| Reid Kleckner | 6fe771a | 2013-12-13 00:53:54 +0000 | [diff] [blame] | 1486 | void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, | 
|  | 1487 | const CXXDestructorDecl *DD, | 
|  | 1488 | CXXDtorType Type, bool ForVirtualBase, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1489 | bool Delegating, Address This) { | 
| Rafael Espindola | 1ac0ec8 | 2014-09-11 15:42:06 +0000 | [diff] [blame] | 1490 | llvm::Value *Callee = CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)); | 
| Reid Kleckner | 6fe771a | 2013-12-13 00:53:54 +0000 | [diff] [blame] | 1491 |  | 
| Timur Iskhodzhanov | f174942 | 2014-03-14 17:43:37 +0000 | [diff] [blame] | 1492 | if (DD->isVirtual()) { | 
|  | 1493 | assert(Type != CXXDtorType::Dtor_Deleting && | 
|  | 1494 | "The deleting destructor should only be called via a virtual call"); | 
|  | 1495 | This = adjustThisArgumentForVirtualFunctionCall(CGF, GlobalDecl(DD, Type), | 
|  | 1496 | This, false); | 
|  | 1497 | } | 
| Reid Kleckner | 6fe771a | 2013-12-13 00:53:54 +0000 | [diff] [blame] | 1498 |  | 
| Alexey Samsonov | ae81bbb | 2016-03-10 00:20:37 +0000 | [diff] [blame] | 1499 | CGF.EmitCXXDestructorCall(DD, Callee, This.getPointer(), | 
|  | 1500 | /*ImplicitParam=*/nullptr, | 
|  | 1501 | /*ImplicitParamTy=*/QualType(), nullptr, | 
|  | 1502 | getFromDtorType(Type)); | 
| Reid Kleckner | 6fe771a | 2013-12-13 00:53:54 +0000 | [diff] [blame] | 1503 | } | 
|  | 1504 |  | 
| Peter Collingbourne | d954601 | 2015-06-19 02:30:43 +0000 | [diff] [blame] | 1505 | void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info, | 
|  | 1506 | const CXXRecordDecl *RD, | 
|  | 1507 | llvm::GlobalVariable *VTable) { | 
| Peter Collingbourne | 3afb266 | 2016-04-28 17:09:37 +0000 | [diff] [blame] | 1508 | if (!CGM.getCodeGenOpts().PrepareForLTO) | 
| Peter Collingbourne | d954601 | 2015-06-19 02:30:43 +0000 | [diff] [blame] | 1509 | return; | 
|  | 1510 |  | 
|  | 1511 | llvm::NamedMDNode *BitsetsMD = | 
|  | 1512 | CGM.getModule().getOrInsertNamedMetadata("llvm.bitsets"); | 
| Peter Collingbourne | d954601 | 2015-06-19 02:30:43 +0000 | [diff] [blame] | 1513 |  | 
| Peter Collingbourne | e570644 | 2015-07-09 19:56:14 +0000 | [diff] [blame] | 1514 | // The location of the first virtual function pointer in the virtual table, | 
|  | 1515 | // aka the "address point" on Itanium. This is at offset 0 if RTTI is | 
|  | 1516 | // disabled, or sizeof(void*) if RTTI is enabled. | 
|  | 1517 | CharUnits AddressPoint = | 
|  | 1518 | getContext().getLangOpts().RTTIData | 
|  | 1519 | ? getContext().toCharUnitsFromBits( | 
|  | 1520 | getContext().getTargetInfo().getPointerWidth(0)) | 
|  | 1521 | : CharUnits::Zero(); | 
| Peter Collingbourne | d954601 | 2015-06-19 02:30:43 +0000 | [diff] [blame] | 1522 |  | 
|  | 1523 | if (Info->PathToBaseWithVPtr.empty()) { | 
| Peter Collingbourne | 3afb266 | 2016-04-28 17:09:37 +0000 | [diff] [blame] | 1524 | CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, RD); | 
| Peter Collingbourne | d954601 | 2015-06-19 02:30:43 +0000 | [diff] [blame] | 1525 | return; | 
|  | 1526 | } | 
|  | 1527 |  | 
|  | 1528 | // Add a bitset entry for the least derived base belonging to this vftable. | 
| Peter Collingbourne | 3afb266 | 2016-04-28 17:09:37 +0000 | [diff] [blame] | 1529 | CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, | 
|  | 1530 | Info->PathToBaseWithVPtr.back()); | 
| Peter Collingbourne | d954601 | 2015-06-19 02:30:43 +0000 | [diff] [blame] | 1531 |  | 
|  | 1532 | // Add a bitset entry for each derived class that is laid out at the same | 
|  | 1533 | // offset as the least derived base. | 
|  | 1534 | for (unsigned I = Info->PathToBaseWithVPtr.size() - 1; I != 0; --I) { | 
|  | 1535 | const CXXRecordDecl *DerivedRD = Info->PathToBaseWithVPtr[I - 1]; | 
|  | 1536 | const CXXRecordDecl *BaseRD = Info->PathToBaseWithVPtr[I]; | 
|  | 1537 |  | 
|  | 1538 | const ASTRecordLayout &Layout = | 
|  | 1539 | getContext().getASTRecordLayout(DerivedRD); | 
|  | 1540 | CharUnits Offset; | 
|  | 1541 | auto VBI = Layout.getVBaseOffsetsMap().find(BaseRD); | 
|  | 1542 | if (VBI == Layout.getVBaseOffsetsMap().end()) | 
|  | 1543 | Offset = Layout.getBaseClassOffset(BaseRD); | 
|  | 1544 | else | 
|  | 1545 | Offset = VBI->second.VBaseOffset; | 
|  | 1546 | if (!Offset.isZero()) | 
|  | 1547 | return; | 
| Peter Collingbourne | 3afb266 | 2016-04-28 17:09:37 +0000 | [diff] [blame] | 1548 | CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, DerivedRD); | 
| Peter Collingbourne | d954601 | 2015-06-19 02:30:43 +0000 | [diff] [blame] | 1549 | } | 
|  | 1550 |  | 
|  | 1551 | // Finally do the same for the most derived class. | 
| Peter Collingbourne | 3afb266 | 2016-04-28 17:09:37 +0000 | [diff] [blame] | 1552 | if (Info->FullOffsetInMDC.isZero()) | 
| Evgeniy Stepanov | fd6f92d | 2015-12-15 23:00:20 +0000 | [diff] [blame] | 1553 | CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, RD); | 
| Peter Collingbourne | d954601 | 2015-06-19 02:30:43 +0000 | [diff] [blame] | 1554 | } | 
|  | 1555 |  | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1556 | void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, | 
|  | 1557 | const CXXRecordDecl *RD) { | 
| Timur Iskhodzhanov | 5877663 | 2013-11-05 15:54:58 +0000 | [diff] [blame] | 1558 | MicrosoftVTableContext &VFTContext = CGM.getMicrosoftVTableContext(); | 
| Benjamin Kramer | 22c68ef | 2014-09-11 14:13:49 +0000 | [diff] [blame] | 1559 | const VPtrInfoVector &VFPtrs = VFTContext.getVFPtrOffsets(RD); | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1560 |  | 
| Warren Hunt | 5c2b4ea | 2014-05-23 16:07:43 +0000 | [diff] [blame] | 1561 | for (VPtrInfo *Info : VFPtrs) { | 
|  | 1562 | llvm::GlobalVariable *VTable = getAddrOfVTable(RD, Info->FullOffsetInMDC); | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1563 | if (VTable->hasInitializer()) | 
|  | 1564 | continue; | 
| David Majnemer | d905da4 | 2014-07-01 20:30:31 +0000 | [diff] [blame] | 1565 |  | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1566 | const VTableLayout &VTLayout = | 
| Warren Hunt | 5c2b4ea | 2014-05-23 16:07:43 +0000 | [diff] [blame] | 1567 | VFTContext.getVFTableLayout(RD, Info->FullOffsetInMDC); | 
| David Majnemer | 470ee61 | 2016-02-09 17:27:52 +0000 | [diff] [blame] | 1568 |  | 
|  | 1569 | llvm::Constant *RTTI = nullptr; | 
|  | 1570 | if (any_of(VTLayout.vtable_components(), | 
|  | 1571 | [](const VTableComponent &VTC) { return VTC.isRTTIKind(); })) | 
|  | 1572 | RTTI = getMSCompleteObjectLocator(RD, Info); | 
|  | 1573 |  | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1574 | llvm::Constant *Init = CGVT.CreateVTableInitializer( | 
|  | 1575 | RD, VTLayout.vtable_component_begin(), | 
|  | 1576 | VTLayout.getNumVTableComponents(), VTLayout.vtable_thunk_begin(), | 
| David Majnemer | d905da4 | 2014-07-01 20:30:31 +0000 | [diff] [blame] | 1577 | VTLayout.getNumVTableThunks(), RTTI); | 
|  | 1578 |  | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1579 | VTable->setInitializer(Init); | 
| Peter Collingbourne | d954601 | 2015-06-19 02:30:43 +0000 | [diff] [blame] | 1580 |  | 
|  | 1581 | emitVTableBitSetEntries(Info, RD, VTable); | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1582 | } | 
|  | 1583 | } | 
|  | 1584 |  | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 1585 | bool MicrosoftCXXABI::isVirtualOffsetNeededForVTableField( | 
|  | 1586 | CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr) { | 
|  | 1587 | return Vptr.NearestVBase != nullptr; | 
|  | 1588 | } | 
|  | 1589 |  | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1590 | llvm::Value *MicrosoftCXXABI::getVTableAddressPointInStructor( | 
|  | 1591 | CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 1592 | const CXXRecordDecl *NearestVBase) { | 
|  | 1593 | llvm::Constant *VTableAddressPoint = getVTableAddressPoint(Base, VTableClass); | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1594 | if (!VTableAddressPoint) { | 
|  | 1595 | assert(Base.getBase()->getNumVBases() && | 
| David Majnemer | 9ced3dd | 2015-03-14 23:44:48 +0000 | [diff] [blame] | 1596 | !getContext().getASTRecordLayout(Base.getBase()).hasOwnVFPtr()); | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1597 | } | 
|  | 1598 | return VTableAddressPoint; | 
|  | 1599 | } | 
|  | 1600 |  | 
| Timur Iskhodzhanov | 6745522 | 2013-10-03 06:26:13 +0000 | [diff] [blame] | 1601 | static void mangleVFTableName(MicrosoftMangleContext &MangleContext, | 
| Reid Kleckner | 9c6e9e3 | 2014-02-27 19:40:09 +0000 | [diff] [blame] | 1602 | const CXXRecordDecl *RD, const VPtrInfo *VFPtr, | 
| Timur Iskhodzhanov | 6745522 | 2013-10-03 06:26:13 +0000 | [diff] [blame] | 1603 | SmallString<256> &Name) { | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1604 | llvm::raw_svector_ostream Out(Name); | 
| Reid Kleckner | 9c6e9e3 | 2014-02-27 19:40:09 +0000 | [diff] [blame] | 1605 | MangleContext.mangleCXXVFTable(RD, VFPtr->MangledPath, Out); | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1606 | } | 
|  | 1607 |  | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 1608 | llvm::Constant * | 
|  | 1609 | MicrosoftCXXABI::getVTableAddressPoint(BaseSubobject Base, | 
|  | 1610 | const CXXRecordDecl *VTableClass) { | 
| Piotr Padlewski | 4bed31b | 2015-09-10 20:18:30 +0000 | [diff] [blame] | 1611 | (void)getAddrOfVTable(VTableClass, Base.getBaseOffset()); | 
|  | 1612 | VFTableIdTy ID(VTableClass, Base.getBaseOffset()); | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 1613 | return VFTablesMap[ID]; | 
|  | 1614 | } | 
|  | 1615 |  | 
|  | 1616 | llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr( | 
|  | 1617 | BaseSubobject Base, const CXXRecordDecl *VTableClass) { | 
|  | 1618 | llvm::Constant *VFTable = getVTableAddressPoint(Base, VTableClass); | 
| David Majnemer | d905da4 | 2014-07-01 20:30:31 +0000 | [diff] [blame] | 1619 | assert(VFTable && "Couldn't find a vftable for the given base?"); | 
|  | 1620 | return VFTable; | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1621 | } | 
|  | 1622 |  | 
|  | 1623 | llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, | 
|  | 1624 | CharUnits VPtrOffset) { | 
|  | 1625 | // getAddrOfVTable may return 0 if asked to get an address of a vtable which | 
|  | 1626 | // shouldn't be used in the given record type. We want to cache this result in | 
|  | 1627 | // VFTablesMap, thus a simple zero check is not sufficient. | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 1628 |  | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1629 | VFTableIdTy ID(RD, VPtrOffset); | 
| David Majnemer | d905da4 | 2014-07-01 20:30:31 +0000 | [diff] [blame] | 1630 | VTablesMapTy::iterator I; | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1631 | bool Inserted; | 
| David Majnemer | d905da4 | 2014-07-01 20:30:31 +0000 | [diff] [blame] | 1632 | std::tie(I, Inserted) = VTablesMap.insert(std::make_pair(ID, nullptr)); | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1633 | if (!Inserted) | 
|  | 1634 | return I->second; | 
|  | 1635 |  | 
|  | 1636 | llvm::GlobalVariable *&VTable = I->second; | 
|  | 1637 |  | 
| Timur Iskhodzhanov | 5877663 | 2013-11-05 15:54:58 +0000 | [diff] [blame] | 1638 | MicrosoftVTableContext &VTContext = CGM.getMicrosoftVTableContext(); | 
| Reid Kleckner | 9c6e9e3 | 2014-02-27 19:40:09 +0000 | [diff] [blame] | 1639 | const VPtrInfoVector &VFPtrs = VTContext.getVFPtrOffsets(RD); | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1640 |  | 
| David Blaikie | 82e95a3 | 2014-11-19 07:49:47 +0000 | [diff] [blame] | 1641 | if (DeferredVFTables.insert(RD).second) { | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1642 | // We haven't processed this record type before. | 
| Eric Christopher | d160c50 | 2016-01-29 01:35:53 +0000 | [diff] [blame] | 1643 | // Queue up this vtable for possible deferred emission. | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1644 | CGM.addDeferredVTable(RD); | 
|  | 1645 |  | 
|  | 1646 | #ifndef NDEBUG | 
|  | 1647 | // Create all the vftables at once in order to make sure each vftable has | 
|  | 1648 | // a unique mangled name. | 
|  | 1649 | llvm::StringSet<> ObservedMangledNames; | 
|  | 1650 | for (size_t J = 0, F = VFPtrs.size(); J != F; ++J) { | 
|  | 1651 | SmallString<256> Name; | 
| Timur Iskhodzhanov | 6745522 | 2013-10-03 06:26:13 +0000 | [diff] [blame] | 1652 | mangleVFTableName(getMangleContext(), RD, VFPtrs[J], Name); | 
| David Blaikie | 61b86d4 | 2014-11-19 02:56:13 +0000 | [diff] [blame] | 1653 | if (!ObservedMangledNames.insert(Name.str()).second) | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1654 | llvm_unreachable("Already saw this mangling before?"); | 
|  | 1655 | } | 
|  | 1656 | #endif | 
|  | 1657 | } | 
|  | 1658 |  | 
| David Majnemer | a03849b | 2015-03-18 22:04:43 +0000 | [diff] [blame] | 1659 | VPtrInfo *const *VFPtrI = | 
|  | 1660 | std::find_if(VFPtrs.begin(), VFPtrs.end(), [&](VPtrInfo *VPI) { | 
|  | 1661 | return VPI->FullOffsetInMDC == VPtrOffset; | 
|  | 1662 | }); | 
|  | 1663 | if (VFPtrI == VFPtrs.end()) { | 
|  | 1664 | VFTablesMap[ID] = nullptr; | 
|  | 1665 | return nullptr; | 
|  | 1666 | } | 
|  | 1667 | VPtrInfo *VFPtr = *VFPtrI; | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1668 |  | 
| David Majnemer | a03849b | 2015-03-18 22:04:43 +0000 | [diff] [blame] | 1669 | SmallString<256> VFTableName; | 
|  | 1670 | mangleVFTableName(getMangleContext(), RD, VFPtr, VFTableName); | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1671 |  | 
| David Majnemer | 2d8b200 | 2016-02-11 17:49:28 +0000 | [diff] [blame] | 1672 | // Classes marked __declspec(dllimport) need vftables generated on the | 
|  | 1673 | // import-side in order to support features like constexpr.  No other | 
|  | 1674 | // translation unit relies on the emission of the local vftable, translation | 
|  | 1675 | // units are expected to generate them as needed. | 
|  | 1676 | // | 
|  | 1677 | // Because of this unique behavior, we maintain this logic here instead of | 
|  | 1678 | // getVTableLinkage. | 
|  | 1679 | llvm::GlobalValue::LinkageTypes VFTableLinkage = | 
|  | 1680 | RD->hasAttr<DLLImportAttr>() ? llvm::GlobalValue::LinkOnceODRLinkage | 
|  | 1681 | : CGM.getVTableLinkage(RD); | 
| David Majnemer | a03849b | 2015-03-18 22:04:43 +0000 | [diff] [blame] | 1682 | bool VFTableComesFromAnotherTU = | 
|  | 1683 | llvm::GlobalValue::isAvailableExternallyLinkage(VFTableLinkage) || | 
|  | 1684 | llvm::GlobalValue::isExternalLinkage(VFTableLinkage); | 
|  | 1685 | bool VTableAliasIsRequred = | 
|  | 1686 | !VFTableComesFromAnotherTU && getContext().getLangOpts().RTTIData; | 
| David Majnemer | bb84871 | 2014-07-01 22:37:08 +0000 | [diff] [blame] | 1687 |  | 
| David Majnemer | a03849b | 2015-03-18 22:04:43 +0000 | [diff] [blame] | 1688 | if (llvm::GlobalValue *VFTable = | 
|  | 1689 | CGM.getModule().getNamedGlobal(VFTableName)) { | 
|  | 1690 | VFTablesMap[ID] = VFTable; | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 1691 | VTable = VTableAliasIsRequred | 
|  | 1692 | ? cast<llvm::GlobalVariable>( | 
|  | 1693 | cast<llvm::GlobalAlias>(VFTable)->getBaseObject()) | 
|  | 1694 | : cast<llvm::GlobalVariable>(VFTable); | 
|  | 1695 | return VTable; | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1696 | } | 
|  | 1697 |  | 
| David Majnemer | a03849b | 2015-03-18 22:04:43 +0000 | [diff] [blame] | 1698 | uint64_t NumVTableSlots = | 
|  | 1699 | VTContext.getVFTableLayout(RD, VFPtr->FullOffsetInMDC) | 
|  | 1700 | .getNumVTableComponents(); | 
|  | 1701 | llvm::GlobalValue::LinkageTypes VTableLinkage = | 
|  | 1702 | VTableAliasIsRequred ? llvm::GlobalValue::PrivateLinkage : VFTableLinkage; | 
|  | 1703 |  | 
|  | 1704 | StringRef VTableName = VTableAliasIsRequred ? StringRef() : VFTableName.str(); | 
|  | 1705 |  | 
|  | 1706 | llvm::ArrayType *VTableType = | 
|  | 1707 | llvm::ArrayType::get(CGM.Int8PtrTy, NumVTableSlots); | 
|  | 1708 |  | 
|  | 1709 | // Create a backing variable for the contents of VTable.  The VTable may | 
|  | 1710 | // or may not include space for a pointer to RTTI data. | 
|  | 1711 | llvm::GlobalValue *VFTable; | 
|  | 1712 | VTable = new llvm::GlobalVariable(CGM.getModule(), VTableType, | 
|  | 1713 | /*isConstant=*/true, VTableLinkage, | 
|  | 1714 | /*Initializer=*/nullptr, VTableName); | 
|  | 1715 | VTable->setUnnamedAddr(true); | 
|  | 1716 |  | 
|  | 1717 | llvm::Comdat *C = nullptr; | 
|  | 1718 | if (!VFTableComesFromAnotherTU && | 
|  | 1719 | (llvm::GlobalValue::isWeakForLinker(VFTableLinkage) || | 
|  | 1720 | (llvm::GlobalValue::isLocalLinkage(VFTableLinkage) && | 
|  | 1721 | VTableAliasIsRequred))) | 
|  | 1722 | C = CGM.getModule().getOrInsertComdat(VFTableName.str()); | 
|  | 1723 |  | 
|  | 1724 | // Only insert a pointer into the VFTable for RTTI data if we are not | 
|  | 1725 | // importing it.  We never reference the RTTI data directly so there is no | 
|  | 1726 | // need to make room for it. | 
|  | 1727 | if (VTableAliasIsRequred) { | 
|  | 1728 | llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.IntTy, 0), | 
|  | 1729 | llvm::ConstantInt::get(CGM.IntTy, 1)}; | 
|  | 1730 | // Create a GEP which points just after the first entry in the VFTable, | 
|  | 1731 | // this should be the location of the first virtual method. | 
| David Blaikie | e3b172a | 2015-04-02 18:55:21 +0000 | [diff] [blame] | 1732 | llvm::Constant *VTableGEP = llvm::ConstantExpr::getInBoundsGetElementPtr( | 
|  | 1733 | VTable->getValueType(), VTable, GEPIndices); | 
| David Majnemer | a03849b | 2015-03-18 22:04:43 +0000 | [diff] [blame] | 1734 | if (llvm::GlobalValue::isWeakForLinker(VFTableLinkage)) { | 
|  | 1735 | VFTableLinkage = llvm::GlobalValue::ExternalLinkage; | 
|  | 1736 | if (C) | 
|  | 1737 | C->setSelectionKind(llvm::Comdat::Largest); | 
|  | 1738 | } | 
| David Blaikie | 2a791d7 | 2015-09-14 18:38:22 +0000 | [diff] [blame] | 1739 | VFTable = llvm::GlobalAlias::create(CGM.Int8PtrTy, | 
|  | 1740 | /*AddressSpace=*/0, VFTableLinkage, | 
|  | 1741 | VFTableName.str(), VTableGEP, | 
|  | 1742 | &CGM.getModule()); | 
| David Majnemer | a03849b | 2015-03-18 22:04:43 +0000 | [diff] [blame] | 1743 | VFTable->setUnnamedAddr(true); | 
|  | 1744 | } else { | 
|  | 1745 | // We don't need a GlobalAlias to be a symbol for the VTable if we won't | 
|  | 1746 | // be referencing any RTTI data. | 
|  | 1747 | // The GlobalVariable will end up being an appropriate definition of the | 
|  | 1748 | // VFTable. | 
|  | 1749 | VFTable = VTable; | 
|  | 1750 | } | 
|  | 1751 | if (C) | 
|  | 1752 | VTable->setComdat(C); | 
|  | 1753 |  | 
| David Majnemer | 2d8b200 | 2016-02-11 17:49:28 +0000 | [diff] [blame] | 1754 | if (RD->hasAttr<DLLExportAttr>()) | 
| David Majnemer | a03849b | 2015-03-18 22:04:43 +0000 | [diff] [blame] | 1755 | VFTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); | 
|  | 1756 |  | 
|  | 1757 | VFTablesMap[ID] = VFTable; | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1758 | return VTable; | 
|  | 1759 | } | 
|  | 1760 |  | 
| Peter Collingbourne | d954601 | 2015-06-19 02:30:43 +0000 | [diff] [blame] | 1761 | // Compute the identity of the most derived class whose virtual table is located | 
|  | 1762 | // at the given offset into RD. | 
|  | 1763 | static const CXXRecordDecl *getClassAtVTableLocation(ASTContext &Ctx, | 
|  | 1764 | const CXXRecordDecl *RD, | 
|  | 1765 | CharUnits Offset) { | 
|  | 1766 | if (Offset.isZero()) | 
|  | 1767 | return RD; | 
|  | 1768 |  | 
|  | 1769 | const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); | 
|  | 1770 | const CXXRecordDecl *MaxBase = nullptr; | 
|  | 1771 | CharUnits MaxBaseOffset; | 
|  | 1772 | for (auto &&B : RD->bases()) { | 
|  | 1773 | const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl(); | 
|  | 1774 | CharUnits BaseOffset = Layout.getBaseClassOffset(Base); | 
| Peter Collingbourne | 3d4114b | 2015-07-08 21:08:08 +0000 | [diff] [blame] | 1775 | if (BaseOffset <= Offset && BaseOffset >= MaxBaseOffset) { | 
| Peter Collingbourne | d954601 | 2015-06-19 02:30:43 +0000 | [diff] [blame] | 1776 | MaxBase = Base; | 
|  | 1777 | MaxBaseOffset = BaseOffset; | 
|  | 1778 | } | 
|  | 1779 | } | 
|  | 1780 | for (auto &&B : RD->vbases()) { | 
|  | 1781 | const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl(); | 
|  | 1782 | CharUnits BaseOffset = Layout.getVBaseClassOffset(Base); | 
| Peter Collingbourne | 3d4114b | 2015-07-08 21:08:08 +0000 | [diff] [blame] | 1783 | if (BaseOffset <= Offset && BaseOffset >= MaxBaseOffset) { | 
| Peter Collingbourne | d954601 | 2015-06-19 02:30:43 +0000 | [diff] [blame] | 1784 | MaxBase = Base; | 
|  | 1785 | MaxBaseOffset = BaseOffset; | 
|  | 1786 | } | 
|  | 1787 | } | 
|  | 1788 | assert(MaxBase); | 
|  | 1789 | return getClassAtVTableLocation(Ctx, MaxBase, Offset - MaxBaseOffset); | 
|  | 1790 | } | 
|  | 1791 |  | 
|  | 1792 | // Compute the identity of the most derived class whose virtual table is located | 
|  | 1793 | // at the MethodVFTableLocation ML. | 
|  | 1794 | static const CXXRecordDecl * | 
|  | 1795 | getClassAtVTableLocation(ASTContext &Ctx, GlobalDecl GD, | 
|  | 1796 | MicrosoftVTableContext::MethodVFTableLocation &ML) { | 
|  | 1797 | const CXXRecordDecl *RD = ML.VBase; | 
|  | 1798 | if (!RD) | 
|  | 1799 | RD = cast<CXXMethodDecl>(GD.getDecl())->getParent(); | 
|  | 1800 |  | 
|  | 1801 | return getClassAtVTableLocation(Ctx, RD, ML.VFPtrOffset); | 
|  | 1802 | } | 
|  | 1803 |  | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 1804 | llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, | 
|  | 1805 | GlobalDecl GD, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1806 | Address This, | 
| Peter Collingbourne | 6708c4a | 2015-06-19 01:51:54 +0000 | [diff] [blame] | 1807 | llvm::Type *Ty, | 
|  | 1808 | SourceLocation Loc) { | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 1809 | GD = GD.getCanonicalDecl(); | 
|  | 1810 | CGBuilderTy &Builder = CGF.Builder; | 
|  | 1811 |  | 
|  | 1812 | Ty = Ty->getPointerTo()->getPointerTo(); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1813 | Address VPtr = | 
| Timur Iskhodzhanov | f174942 | 2014-03-14 17:43:37 +0000 | [diff] [blame] | 1814 | adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true); | 
| Piotr Padlewski | 4b1ac72 | 2015-09-15 21:46:55 +0000 | [diff] [blame] | 1815 |  | 
|  | 1816 | auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl()); | 
|  | 1817 | llvm::Value *VTable = CGF.GetVTablePtr(VPtr, Ty, MethodDecl->getParent()); | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 1818 |  | 
| Timur Iskhodzhanov | 5877663 | 2013-11-05 15:54:58 +0000 | [diff] [blame] | 1819 | MicrosoftVTableContext::MethodVFTableLocation ML = | 
|  | 1820 | CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD); | 
| Peter Collingbourne | 3afb266 | 2016-04-28 17:09:37 +0000 | [diff] [blame] | 1821 | if (CGM.getCodeGenOpts().PrepareForLTO) | 
| Peter Collingbourne | fb532b9 | 2016-02-24 20:46:36 +0000 | [diff] [blame] | 1822 | CGF.EmitBitSetCodeForVCall(getClassAtVTableLocation(getContext(), GD, ML), | 
|  | 1823 | VTable, Loc); | 
| Peter Collingbourne | d954601 | 2015-06-19 02:30:43 +0000 | [diff] [blame] | 1824 |  | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 1825 | llvm::Value *VFuncPtr = | 
|  | 1826 | Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn"); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1827 | return Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign()); | 
| Timur Iskhodzhanov | 88fd439 | 2013-08-21 06:25:03 +0000 | [diff] [blame] | 1828 | } | 
|  | 1829 |  | 
| David Majnemer | 0c0b6d9 | 2014-10-31 20:09:12 +0000 | [diff] [blame] | 1830 | llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall( | 
|  | 1831 | CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1832 | Address This, const CXXMemberCallExpr *CE) { | 
| Alexey Samsonov | a5bf76b | 2014-08-25 20:17:35 +0000 | [diff] [blame] | 1833 | assert(CE == nullptr || CE->arg_begin() == CE->arg_end()); | 
| Timur Iskhodzhanov | d619711 | 2013-02-15 14:45:22 +0000 | [diff] [blame] | 1834 | assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete); | 
|  | 1835 |  | 
|  | 1836 | // We have only one destructor in the vftable but can get both behaviors | 
| Timur Iskhodzhanov | 701981f | 2013-08-27 10:38:19 +0000 | [diff] [blame] | 1837 | // by passing an implicit int parameter. | 
| Timur Iskhodzhanov | 62082b7 | 2013-10-16 18:24:06 +0000 | [diff] [blame] | 1838 | GlobalDecl GD(Dtor, Dtor_Deleting); | 
| Rafael Espindola | 8d2a19b | 2014-09-08 16:01:27 +0000 | [diff] [blame] | 1839 | const CGFunctionInfo *FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration( | 
|  | 1840 | Dtor, StructorType::Deleting); | 
| Timur Iskhodzhanov | d619711 | 2013-02-15 14:45:22 +0000 | [diff] [blame] | 1841 | llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo); | 
| Peter Collingbourne | 6708c4a | 2015-06-19 01:51:54 +0000 | [diff] [blame] | 1842 | llvm::Value *Callee = getVirtualFunctionPointer( | 
|  | 1843 | CGF, GD, This, Ty, CE ? CE->getLocStart() : SourceLocation()); | 
| Timur Iskhodzhanov | d619711 | 2013-02-15 14:45:22 +0000 | [diff] [blame] | 1844 |  | 
| David Majnemer | 9ced3dd | 2015-03-14 23:44:48 +0000 | [diff] [blame] | 1845 | ASTContext &Context = getContext(); | 
| Nico Weber | 0a02992 | 2015-01-12 21:24:10 +0000 | [diff] [blame] | 1846 | llvm::Value *ImplicitParam = llvm::ConstantInt::get( | 
|  | 1847 | llvm::IntegerType::getInt32Ty(CGF.getLLVMContext()), | 
|  | 1848 | DtorType == Dtor_Deleting); | 
| Timur Iskhodzhanov | d619711 | 2013-02-15 14:45:22 +0000 | [diff] [blame] | 1849 |  | 
| Timur Iskhodzhanov | f174942 | 2014-03-14 17:43:37 +0000 | [diff] [blame] | 1850 | This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true); | 
| Alexey Samsonov | ae81bbb | 2016-03-10 00:20:37 +0000 | [diff] [blame] | 1851 | RValue RV = | 
|  | 1852 | CGF.EmitCXXDestructorCall(Dtor, Callee, This.getPointer(), ImplicitParam, | 
|  | 1853 | Context.IntTy, CE, StructorType::Deleting); | 
| David Majnemer | 0c0b6d9 | 2014-10-31 20:09:12 +0000 | [diff] [blame] | 1854 | return RV.getScalarVal(); | 
| Timur Iskhodzhanov | d619711 | 2013-02-15 14:45:22 +0000 | [diff] [blame] | 1855 | } | 
|  | 1856 |  | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 1857 | const VBTableGlobals & | 
|  | 1858 | MicrosoftCXXABI::enumerateVBTables(const CXXRecordDecl *RD) { | 
| Reid Kleckner | 7810af0 | 2013-06-19 15:20:38 +0000 | [diff] [blame] | 1859 | // At this layer, we can key the cache off of a single class, which is much | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 1860 | // easier than caching each vbtable individually. | 
|  | 1861 | llvm::DenseMap<const CXXRecordDecl*, VBTableGlobals>::iterator Entry; | 
|  | 1862 | bool Added; | 
| Benjamin Kramer | 867ea1d | 2014-03-02 13:01:17 +0000 | [diff] [blame] | 1863 | std::tie(Entry, Added) = | 
|  | 1864 | VBTablesMap.insert(std::make_pair(RD, VBTableGlobals())); | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 1865 | VBTableGlobals &VBGlobals = Entry->second; | 
|  | 1866 | if (!Added) | 
|  | 1867 | return VBGlobals; | 
| Reid Kleckner | 7810af0 | 2013-06-19 15:20:38 +0000 | [diff] [blame] | 1868 |  | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 1869 | MicrosoftVTableContext &Context = CGM.getMicrosoftVTableContext(); | 
|  | 1870 | VBGlobals.VBTables = &Context.enumerateVBTables(RD); | 
| Reid Kleckner | 7810af0 | 2013-06-19 15:20:38 +0000 | [diff] [blame] | 1871 |  | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 1872 | // Cache the globals for all vbtables so we don't have to recompute the | 
|  | 1873 | // mangled names. | 
|  | 1874 | llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD); | 
| Reid Kleckner | 9c6e9e3 | 2014-02-27 19:40:09 +0000 | [diff] [blame] | 1875 | for (VPtrInfoVector::const_iterator I = VBGlobals.VBTables->begin(), | 
|  | 1876 | E = VBGlobals.VBTables->end(); | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 1877 | I != E; ++I) { | 
| Reid Kleckner | 5f08094 | 2014-01-03 23:42:00 +0000 | [diff] [blame] | 1878 | VBGlobals.Globals.push_back(getAddrOfVBTable(**I, RD, Linkage)); | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 1879 | } | 
|  | 1880 |  | 
|  | 1881 | return VBGlobals; | 
| Reid Kleckner | 7810af0 | 2013-06-19 15:20:38 +0000 | [diff] [blame] | 1882 | } | 
|  | 1883 |  | 
| Reid Kleckner | e4a5220 | 2014-02-21 02:27:32 +0000 | [diff] [blame] | 1884 | llvm::Function *MicrosoftCXXABI::EmitVirtualMemPtrThunk( | 
|  | 1885 | const CXXMethodDecl *MD, | 
|  | 1886 | const MicrosoftVTableContext::MethodVFTableLocation &ML) { | 
| Reid Kleckner | c347351 | 2014-08-29 21:43:29 +0000 | [diff] [blame] | 1887 | assert(!isa<CXXConstructorDecl>(MD) && !isa<CXXDestructorDecl>(MD) && | 
|  | 1888 | "can't form pointers to ctors or virtual dtors"); | 
|  | 1889 |  | 
| Reid Kleckner | e4a5220 | 2014-02-21 02:27:32 +0000 | [diff] [blame] | 1890 | // Calculate the mangled name. | 
|  | 1891 | SmallString<256> ThunkName; | 
|  | 1892 | llvm::raw_svector_ostream Out(ThunkName); | 
|  | 1893 | getMangleContext().mangleVirtualMemPtrThunk(MD, Out); | 
| Reid Kleckner | e4a5220 | 2014-02-21 02:27:32 +0000 | [diff] [blame] | 1894 |  | 
| Hans Wennborg | 88497d6 | 2013-11-15 17:24:45 +0000 | [diff] [blame] | 1895 | // If the thunk has been generated previously, just return it. | 
|  | 1896 | if (llvm::GlobalValue *GV = CGM.getModule().getNamedValue(ThunkName)) | 
|  | 1897 | return cast<llvm::Function>(GV); | 
|  | 1898 |  | 
|  | 1899 | // Create the llvm::Function. | 
| Reid Kleckner | c347351 | 2014-08-29 21:43:29 +0000 | [diff] [blame] | 1900 | const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeMSMemberPointerThunk(MD); | 
| Hans Wennborg | 88497d6 | 2013-11-15 17:24:45 +0000 | [diff] [blame] | 1901 | llvm::FunctionType *ThunkTy = CGM.getTypes().GetFunctionType(FnInfo); | 
|  | 1902 | llvm::Function *ThunkFn = | 
|  | 1903 | llvm::Function::Create(ThunkTy, llvm::Function::ExternalLinkage, | 
|  | 1904 | ThunkName.str(), &CGM.getModule()); | 
|  | 1905 | assert(ThunkFn->getName() == ThunkName && "name was uniqued!"); | 
|  | 1906 |  | 
| Hans Wennborg | 88497d6 | 2013-11-15 17:24:45 +0000 | [diff] [blame] | 1907 | ThunkFn->setLinkage(MD->isExternallyVisible() | 
|  | 1908 | ? llvm::GlobalValue::LinkOnceODRLinkage | 
|  | 1909 | : llvm::GlobalValue::InternalLinkage); | 
| David Majnemer | 8c9cdb6 | 2015-01-21 01:21:31 +0000 | [diff] [blame] | 1910 | if (MD->isExternallyVisible()) | 
|  | 1911 | ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName())); | 
| Hans Wennborg | 88497d6 | 2013-11-15 17:24:45 +0000 | [diff] [blame] | 1912 |  | 
|  | 1913 | CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn); | 
|  | 1914 | CGM.SetLLVMFunctionAttributesForDefinition(MD, ThunkFn); | 
|  | 1915 |  | 
| Reid Kleckner | 9da9448 | 2015-01-21 22:18:17 +0000 | [diff] [blame] | 1916 | // Add the "thunk" attribute so that LLVM knows that the return type is | 
|  | 1917 | // meaningless. These thunks can be used to call functions with differing | 
|  | 1918 | // return types, and the caller is required to cast the prototype | 
|  | 1919 | // appropriately to extract the correct value. | 
|  | 1920 | ThunkFn->addFnAttr("thunk"); | 
|  | 1921 |  | 
| Reid Kleckner | b9538a6 | 2014-08-15 18:12:40 +0000 | [diff] [blame] | 1922 | // These thunks can be compared, so they are not unnamed. | 
|  | 1923 | ThunkFn->setUnnamedAddr(false); | 
|  | 1924 |  | 
| Hans Wennborg | 88497d6 | 2013-11-15 17:24:45 +0000 | [diff] [blame] | 1925 | // Start codegen. | 
|  | 1926 | CodeGenFunction CGF(CGM); | 
| Reid Kleckner | c347351 | 2014-08-29 21:43:29 +0000 | [diff] [blame] | 1927 | CGF.CurGD = GlobalDecl(MD); | 
|  | 1928 | CGF.CurFuncIsThunk = true; | 
|  | 1929 |  | 
|  | 1930 | // Build FunctionArgs, but only include the implicit 'this' parameter | 
|  | 1931 | // declaration. | 
|  | 1932 | FunctionArgList FunctionArgs; | 
|  | 1933 | buildThisParam(CGF, FunctionArgs); | 
|  | 1934 |  | 
|  | 1935 | // Start defining the function. | 
|  | 1936 | CGF.StartFunction(GlobalDecl(), FnInfo.getReturnType(), ThunkFn, FnInfo, | 
|  | 1937 | FunctionArgs, MD->getLocation(), SourceLocation()); | 
|  | 1938 | EmitThisParam(CGF); | 
| Hans Wennborg | 88497d6 | 2013-11-15 17:24:45 +0000 | [diff] [blame] | 1939 |  | 
| Reid Kleckner | e4a5220 | 2014-02-21 02:27:32 +0000 | [diff] [blame] | 1940 | // Load the vfptr and then callee from the vftable.  The callee should have | 
|  | 1941 | // adjusted 'this' so that the vfptr is at offset zero. | 
| Reid Kleckner | c347351 | 2014-08-29 21:43:29 +0000 | [diff] [blame] | 1942 | llvm::Value *VTable = CGF.GetVTablePtr( | 
| Piotr Padlewski | 4b1ac72 | 2015-09-15 21:46:55 +0000 | [diff] [blame] | 1943 | getThisAddress(CGF), ThunkTy->getPointerTo()->getPointerTo(), MD->getParent()); | 
|  | 1944 |  | 
| Reid Kleckner | e4a5220 | 2014-02-21 02:27:32 +0000 | [diff] [blame] | 1945 | llvm::Value *VFuncPtr = | 
|  | 1946 | CGF.Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn"); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1947 | llvm::Value *Callee = | 
|  | 1948 | CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign()); | 
| Hans Wennborg | 88497d6 | 2013-11-15 17:24:45 +0000 | [diff] [blame] | 1949 |  | 
| Reid Kleckner | c347351 | 2014-08-29 21:43:29 +0000 | [diff] [blame] | 1950 | CGF.EmitMustTailThunk(MD, getThisValue(CGF), Callee); | 
| Hans Wennborg | 88497d6 | 2013-11-15 17:24:45 +0000 | [diff] [blame] | 1951 |  | 
|  | 1952 | return ThunkFn; | 
|  | 1953 | } | 
|  | 1954 |  | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 1955 | void MicrosoftCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) { | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 1956 | const VBTableGlobals &VBGlobals = enumerateVBTables(RD); | 
|  | 1957 | for (unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) { | 
| Reid Kleckner | 9c6e9e3 | 2014-02-27 19:40:09 +0000 | [diff] [blame] | 1958 | const VPtrInfo *VBT = (*VBGlobals.VBTables)[I]; | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 1959 | llvm::GlobalVariable *GV = VBGlobals.Globals[I]; | 
| David Majnemer | 129f417 | 2015-02-02 10:22:20 +0000 | [diff] [blame] | 1960 | if (GV->isDeclaration()) | 
|  | 1961 | emitVBTableDefinition(*VBT, RD, GV); | 
| Reid Kleckner | 7810af0 | 2013-06-19 15:20:38 +0000 | [diff] [blame] | 1962 | } | 
|  | 1963 | } | 
|  | 1964 |  | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 1965 | llvm::GlobalVariable * | 
| Reid Kleckner | 9c6e9e3 | 2014-02-27 19:40:09 +0000 | [diff] [blame] | 1966 | MicrosoftCXXABI::getAddrOfVBTable(const VPtrInfo &VBT, const CXXRecordDecl *RD, | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 1967 | llvm::GlobalVariable::LinkageTypes Linkage) { | 
|  | 1968 | SmallString<256> OutName; | 
|  | 1969 | llvm::raw_svector_ostream Out(OutName); | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 1970 | getMangleContext().mangleCXXVBTable(RD, VBT.MangledPath, Out); | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 1971 | StringRef Name = OutName.str(); | 
|  | 1972 |  | 
|  | 1973 | llvm::ArrayType *VBTableType = | 
|  | 1974 | llvm::ArrayType::get(CGM.IntTy, 1 + VBT.ReusingBase->getNumVBases()); | 
|  | 1975 |  | 
|  | 1976 | assert(!CGM.getModule().getNamedGlobal(Name) && | 
|  | 1977 | "vbtable with this name already exists: mangling bug?"); | 
|  | 1978 | llvm::GlobalVariable *GV = | 
|  | 1979 | CGM.CreateOrReplaceCXXRuntimeVariable(Name, VBTableType, Linkage); | 
|  | 1980 | GV->setUnnamedAddr(true); | 
| Hans Wennborg | 853ae94 | 2014-05-30 16:59:42 +0000 | [diff] [blame] | 1981 |  | 
|  | 1982 | if (RD->hasAttr<DLLImportAttr>()) | 
|  | 1983 | GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); | 
|  | 1984 | else if (RD->hasAttr<DLLExportAttr>()) | 
|  | 1985 | GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); | 
|  | 1986 |  | 
| David Majnemer | 129f417 | 2015-02-02 10:22:20 +0000 | [diff] [blame] | 1987 | if (!GV->hasExternalLinkage()) | 
|  | 1988 | emitVBTableDefinition(VBT, RD, GV); | 
|  | 1989 |  | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 1990 | return GV; | 
|  | 1991 | } | 
|  | 1992 |  | 
| Reid Kleckner | 9c6e9e3 | 2014-02-27 19:40:09 +0000 | [diff] [blame] | 1993 | void MicrosoftCXXABI::emitVBTableDefinition(const VPtrInfo &VBT, | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 1994 | const CXXRecordDecl *RD, | 
|  | 1995 | llvm::GlobalVariable *GV) const { | 
|  | 1996 | const CXXRecordDecl *ReusingBase = VBT.ReusingBase; | 
|  | 1997 |  | 
|  | 1998 | assert(RD->getNumVBases() && ReusingBase->getNumVBases() && | 
|  | 1999 | "should only emit vbtables for classes with vbtables"); | 
|  | 2000 |  | 
|  | 2001 | const ASTRecordLayout &BaseLayout = | 
| David Majnemer | 9ced3dd | 2015-03-14 23:44:48 +0000 | [diff] [blame] | 2002 | getContext().getASTRecordLayout(VBT.BaseWithVPtr); | 
|  | 2003 | const ASTRecordLayout &DerivedLayout = getContext().getASTRecordLayout(RD); | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 2004 |  | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 2005 | SmallVector<llvm::Constant *, 4> Offsets(1 + ReusingBase->getNumVBases(), | 
|  | 2006 | nullptr); | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 2007 |  | 
|  | 2008 | // The offset from ReusingBase's vbptr to itself always leads. | 
|  | 2009 | CharUnits VBPtrOffset = BaseLayout.getVBPtrOffset(); | 
|  | 2010 | Offsets[0] = llvm::ConstantInt::get(CGM.IntTy, -VBPtrOffset.getQuantity()); | 
|  | 2011 |  | 
|  | 2012 | MicrosoftVTableContext &Context = CGM.getMicrosoftVTableContext(); | 
| Aaron Ballman | 445a939 | 2014-03-13 16:15:17 +0000 | [diff] [blame] | 2013 | for (const auto &I : ReusingBase->vbases()) { | 
|  | 2014 | const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl(); | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 2015 | CharUnits Offset = DerivedLayout.getVBaseClassOffset(VBase); | 
|  | 2016 | assert(!Offset.isNegative()); | 
| Reid Kleckner | 5f08094 | 2014-01-03 23:42:00 +0000 | [diff] [blame] | 2017 |  | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 2018 | // Make it relative to the subobject vbptr. | 
| Reid Kleckner | 5f08094 | 2014-01-03 23:42:00 +0000 | [diff] [blame] | 2019 | CharUnits CompleteVBPtrOffset = VBT.NonVirtualOffset + VBPtrOffset; | 
| Reid Kleckner | 9c6e9e3 | 2014-02-27 19:40:09 +0000 | [diff] [blame] | 2020 | if (VBT.getVBaseWithVPtr()) | 
| Reid Kleckner | 5f08094 | 2014-01-03 23:42:00 +0000 | [diff] [blame] | 2021 | CompleteVBPtrOffset += | 
| Reid Kleckner | 9c6e9e3 | 2014-02-27 19:40:09 +0000 | [diff] [blame] | 2022 | DerivedLayout.getVBaseClassOffset(VBT.getVBaseWithVPtr()); | 
| Reid Kleckner | 5f08094 | 2014-01-03 23:42:00 +0000 | [diff] [blame] | 2023 | Offset -= CompleteVBPtrOffset; | 
|  | 2024 |  | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 2025 | unsigned VBIndex = Context.getVBTableIndex(ReusingBase, VBase); | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 2026 | assert(Offsets[VBIndex] == nullptr && "The same vbindex seen twice?"); | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 2027 | Offsets[VBIndex] = llvm::ConstantInt::get(CGM.IntTy, Offset.getQuantity()); | 
|  | 2028 | } | 
|  | 2029 |  | 
|  | 2030 | assert(Offsets.size() == | 
|  | 2031 | cast<llvm::ArrayType>(cast<llvm::PointerType>(GV->getType()) | 
|  | 2032 | ->getElementType())->getNumElements()); | 
|  | 2033 | llvm::ArrayType *VBTableType = | 
|  | 2034 | llvm::ArrayType::get(CGM.IntTy, Offsets.size()); | 
|  | 2035 | llvm::Constant *Init = llvm::ConstantArray::get(VBTableType, Offsets); | 
|  | 2036 | GV->setInitializer(Init); | 
| David Majnemer | 46e39cc | 2016-02-22 17:22:08 +0000 | [diff] [blame] | 2037 |  | 
|  | 2038 | if (RD->hasAttr<DLLImportAttr>()) | 
|  | 2039 | GV->setLinkage(llvm::GlobalVariable::AvailableExternallyLinkage); | 
| Reid Kleckner | b40a27d | 2014-01-03 00:14:35 +0000 | [diff] [blame] | 2040 | } | 
|  | 2041 |  | 
| Timur Iskhodzhanov | 0201432 | 2013-10-30 11:55:43 +0000 | [diff] [blame] | 2042 | llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2043 | Address This, | 
| Timur Iskhodzhanov | 0201432 | 2013-10-30 11:55:43 +0000 | [diff] [blame] | 2044 | const ThisAdjustment &TA) { | 
|  | 2045 | if (TA.isEmpty()) | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2046 | return This.getPointer(); | 
| Timur Iskhodzhanov | 0201432 | 2013-10-30 11:55:43 +0000 | [diff] [blame] | 2047 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2048 | This = CGF.Builder.CreateElementBitCast(This, CGF.Int8Ty); | 
| Timur Iskhodzhanov | 0201432 | 2013-10-30 11:55:43 +0000 | [diff] [blame] | 2049 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2050 | llvm::Value *V; | 
|  | 2051 | if (TA.Virtual.isEmpty()) { | 
|  | 2052 | V = This.getPointer(); | 
|  | 2053 | } else { | 
| Timur Iskhodzhanov | 053142a | 2013-11-06 06:24:31 +0000 | [diff] [blame] | 2054 | assert(TA.Virtual.Microsoft.VtordispOffset < 0); | 
|  | 2055 | // Adjust the this argument based on the vtordisp value. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2056 | Address VtorDispPtr = | 
|  | 2057 | CGF.Builder.CreateConstInBoundsByteGEP(This, | 
|  | 2058 | CharUnits::fromQuantity(TA.Virtual.Microsoft.VtordispOffset)); | 
|  | 2059 | VtorDispPtr = CGF.Builder.CreateElementBitCast(VtorDispPtr, CGF.Int32Ty); | 
| Timur Iskhodzhanov | 053142a | 2013-11-06 06:24:31 +0000 | [diff] [blame] | 2060 | llvm::Value *VtorDisp = CGF.Builder.CreateLoad(VtorDispPtr, "vtordisp"); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2061 | V = CGF.Builder.CreateGEP(This.getPointer(), | 
|  | 2062 | CGF.Builder.CreateNeg(VtorDisp)); | 
|  | 2063 |  | 
|  | 2064 | // Unfortunately, having applied the vtordisp means that we no | 
|  | 2065 | // longer really have a known alignment for the vbptr step. | 
|  | 2066 | // We'll assume the vbptr is pointer-aligned. | 
| Timur Iskhodzhanov | 053142a | 2013-11-06 06:24:31 +0000 | [diff] [blame] | 2067 |  | 
|  | 2068 | if (TA.Virtual.Microsoft.VBPtrOffset) { | 
|  | 2069 | // If the final overrider is defined in a virtual base other than the one | 
|  | 2070 | // that holds the vfptr, we have to use a vtordispex thunk which looks up | 
|  | 2071 | // the vbtable of the derived class. | 
|  | 2072 | assert(TA.Virtual.Microsoft.VBPtrOffset > 0); | 
|  | 2073 | assert(TA.Virtual.Microsoft.VBOffsetOffset >= 0); | 
|  | 2074 | llvm::Value *VBPtr; | 
|  | 2075 | llvm::Value *VBaseOffset = | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2076 | GetVBaseOffsetFromVBPtr(CGF, Address(V, CGF.getPointerAlign()), | 
|  | 2077 | -TA.Virtual.Microsoft.VBPtrOffset, | 
| Timur Iskhodzhanov | 053142a | 2013-11-06 06:24:31 +0000 | [diff] [blame] | 2078 | TA.Virtual.Microsoft.VBOffsetOffset, &VBPtr); | 
|  | 2079 | V = CGF.Builder.CreateInBoundsGEP(VBPtr, VBaseOffset); | 
|  | 2080 | } | 
|  | 2081 | } | 
| Timur Iskhodzhanov | 0201432 | 2013-10-30 11:55:43 +0000 | [diff] [blame] | 2082 |  | 
|  | 2083 | if (TA.NonVirtual) { | 
|  | 2084 | // Non-virtual adjustment might result in a pointer outside the allocated | 
|  | 2085 | // object, e.g. if the final overrider class is laid out after the virtual | 
|  | 2086 | // base that declares a method in the most derived class. | 
|  | 2087 | V = CGF.Builder.CreateConstGEP1_32(V, TA.NonVirtual); | 
|  | 2088 | } | 
|  | 2089 |  | 
|  | 2090 | // Don't need to bitcast back, the call CodeGen will handle this. | 
|  | 2091 | return V; | 
|  | 2092 | } | 
|  | 2093 |  | 
|  | 2094 | llvm::Value * | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2095 | MicrosoftCXXABI::performReturnAdjustment(CodeGenFunction &CGF, Address Ret, | 
| Timur Iskhodzhanov | 0201432 | 2013-10-30 11:55:43 +0000 | [diff] [blame] | 2096 | const ReturnAdjustment &RA) { | 
|  | 2097 | if (RA.isEmpty()) | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2098 | return Ret.getPointer(); | 
| Timur Iskhodzhanov | 0201432 | 2013-10-30 11:55:43 +0000 | [diff] [blame] | 2099 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2100 | auto OrigTy = Ret.getType(); | 
|  | 2101 | Ret = CGF.Builder.CreateElementBitCast(Ret, CGF.Int8Ty); | 
| Timur Iskhodzhanov | 0201432 | 2013-10-30 11:55:43 +0000 | [diff] [blame] | 2102 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2103 | llvm::Value *V = Ret.getPointer(); | 
| Timur Iskhodzhanov | 0201432 | 2013-10-30 11:55:43 +0000 | [diff] [blame] | 2104 | if (RA.Virtual.Microsoft.VBIndex) { | 
|  | 2105 | assert(RA.Virtual.Microsoft.VBIndex > 0); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2106 | int32_t IntSize = CGF.getIntSize().getQuantity(); | 
| Timur Iskhodzhanov | 0201432 | 2013-10-30 11:55:43 +0000 | [diff] [blame] | 2107 | llvm::Value *VBPtr; | 
|  | 2108 | llvm::Value *VBaseOffset = | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2109 | GetVBaseOffsetFromVBPtr(CGF, Ret, RA.Virtual.Microsoft.VBPtrOffset, | 
| Timur Iskhodzhanov | 0201432 | 2013-10-30 11:55:43 +0000 | [diff] [blame] | 2110 | IntSize * RA.Virtual.Microsoft.VBIndex, &VBPtr); | 
|  | 2111 | V = CGF.Builder.CreateInBoundsGEP(VBPtr, VBaseOffset); | 
|  | 2112 | } | 
|  | 2113 |  | 
|  | 2114 | if (RA.NonVirtual) | 
| David Blaikie | fb901c7a | 2015-04-04 15:12:29 +0000 | [diff] [blame] | 2115 | V = CGF.Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, V, RA.NonVirtual); | 
| Timur Iskhodzhanov | 0201432 | 2013-10-30 11:55:43 +0000 | [diff] [blame] | 2116 |  | 
|  | 2117 | // Cast back to the original type. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2118 | return CGF.Builder.CreateBitCast(V, OrigTy); | 
| Timur Iskhodzhanov | 0201432 | 2013-10-30 11:55:43 +0000 | [diff] [blame] | 2119 | } | 
|  | 2120 |  | 
| John McCall | b91cd66 | 2012-05-01 05:23:51 +0000 | [diff] [blame] | 2121 | bool MicrosoftCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr, | 
|  | 2122 | QualType elementType) { | 
|  | 2123 | // Microsoft seems to completely ignore the possibility of a | 
|  | 2124 | // two-argument usual deallocation function. | 
|  | 2125 | return elementType.isDestructedType(); | 
|  | 2126 | } | 
|  | 2127 |  | 
|  | 2128 | bool MicrosoftCXXABI::requiresArrayCookie(const CXXNewExpr *expr) { | 
|  | 2129 | // Microsoft seems to completely ignore the possibility of a | 
|  | 2130 | // two-argument usual deallocation function. | 
|  | 2131 | return expr->getAllocatedType().isDestructedType(); | 
|  | 2132 | } | 
|  | 2133 |  | 
|  | 2134 | CharUnits MicrosoftCXXABI::getArrayCookieSizeImpl(QualType type) { | 
|  | 2135 | // The array cookie is always a size_t; we then pad that out to the | 
|  | 2136 | // alignment of the element type. | 
|  | 2137 | ASTContext &Ctx = getContext(); | 
|  | 2138 | return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()), | 
|  | 2139 | Ctx.getTypeAlignInChars(type)); | 
|  | 2140 | } | 
|  | 2141 |  | 
|  | 2142 | llvm::Value *MicrosoftCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2143 | Address allocPtr, | 
| John McCall | b91cd66 | 2012-05-01 05:23:51 +0000 | [diff] [blame] | 2144 | CharUnits cookieSize) { | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2145 | Address numElementsPtr = | 
|  | 2146 | CGF.Builder.CreateElementBitCast(allocPtr, CGF.SizeTy); | 
| John McCall | b91cd66 | 2012-05-01 05:23:51 +0000 | [diff] [blame] | 2147 | return CGF.Builder.CreateLoad(numElementsPtr); | 
|  | 2148 | } | 
|  | 2149 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2150 | Address MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, | 
|  | 2151 | Address newPtr, | 
|  | 2152 | llvm::Value *numElements, | 
|  | 2153 | const CXXNewExpr *expr, | 
|  | 2154 | QualType elementType) { | 
| John McCall | b91cd66 | 2012-05-01 05:23:51 +0000 | [diff] [blame] | 2155 | assert(requiresArrayCookie(expr)); | 
|  | 2156 |  | 
|  | 2157 | // The size of the cookie. | 
|  | 2158 | CharUnits cookieSize = getArrayCookieSizeImpl(elementType); | 
|  | 2159 |  | 
|  | 2160 | // Compute an offset to the cookie. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2161 | Address cookiePtr = newPtr; | 
| John McCall | b91cd66 | 2012-05-01 05:23:51 +0000 | [diff] [blame] | 2162 |  | 
|  | 2163 | // Write the number of elements into the appropriate slot. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2164 | Address numElementsPtr | 
|  | 2165 | = CGF.Builder.CreateElementBitCast(cookiePtr, CGF.SizeTy); | 
| John McCall | b91cd66 | 2012-05-01 05:23:51 +0000 | [diff] [blame] | 2166 | CGF.Builder.CreateStore(numElements, numElementsPtr); | 
|  | 2167 |  | 
|  | 2168 | // Finally, compute a pointer to the actual data buffer by skipping | 
|  | 2169 | // over the cookie completely. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2170 | return CGF.Builder.CreateConstInBoundsByteGEP(newPtr, cookieSize); | 
| John McCall | b91cd66 | 2012-05-01 05:23:51 +0000 | [diff] [blame] | 2171 | } | 
|  | 2172 |  | 
| David Majnemer | b3341ea | 2014-10-05 05:05:40 +0000 | [diff] [blame] | 2173 | static void emitGlobalDtorWithTLRegDtor(CodeGenFunction &CGF, const VarDecl &VD, | 
|  | 2174 | llvm::Constant *Dtor, | 
|  | 2175 | llvm::Constant *Addr) { | 
|  | 2176 | // Create a function which calls the destructor. | 
|  | 2177 | llvm::Constant *DtorStub = CGF.createAtExitStub(VD, Dtor, Addr); | 
|  | 2178 |  | 
|  | 2179 | // extern "C" int __tlregdtor(void (*f)(void)); | 
|  | 2180 | llvm::FunctionType *TLRegDtorTy = llvm::FunctionType::get( | 
|  | 2181 | CGF.IntTy, DtorStub->getType(), /*IsVarArg=*/false); | 
|  | 2182 |  | 
|  | 2183 | llvm::Constant *TLRegDtor = | 
|  | 2184 | CGF.CGM.CreateRuntimeFunction(TLRegDtorTy, "__tlregdtor"); | 
|  | 2185 | if (llvm::Function *TLRegDtorFn = dyn_cast<llvm::Function>(TLRegDtor)) | 
|  | 2186 | TLRegDtorFn->setDoesNotThrow(); | 
|  | 2187 |  | 
|  | 2188 | CGF.EmitNounwindRuntimeCall(TLRegDtor, DtorStub); | 
|  | 2189 | } | 
|  | 2190 |  | 
|  | 2191 | void MicrosoftCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, | 
|  | 2192 | llvm::Constant *Dtor, | 
|  | 2193 | llvm::Constant *Addr) { | 
|  | 2194 | if (D.getTLSKind()) | 
|  | 2195 | return emitGlobalDtorWithTLRegDtor(CGF, D, Dtor, Addr); | 
|  | 2196 |  | 
|  | 2197 | // The default behavior is to use atexit. | 
|  | 2198 | CGF.registerGlobalDtorWithAtExit(D, Dtor, Addr); | 
|  | 2199 | } | 
|  | 2200 |  | 
|  | 2201 | void MicrosoftCXXABI::EmitThreadLocalInitFuncs( | 
| Richard Smith | 5a99c49 | 2015-12-01 01:10:48 +0000 | [diff] [blame] | 2202 | CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals, | 
| David Majnemer | b3341ea | 2014-10-05 05:05:40 +0000 | [diff] [blame] | 2203 | ArrayRef<llvm::Function *> CXXThreadLocalInits, | 
| Richard Smith | 5a99c49 | 2015-12-01 01:10:48 +0000 | [diff] [blame] | 2204 | ArrayRef<const VarDecl *> CXXThreadLocalInitVars) { | 
| David Majnemer | b3341ea | 2014-10-05 05:05:40 +0000 | [diff] [blame] | 2205 | // This will create a GV in the .CRT$XDU section.  It will point to our | 
|  | 2206 | // initialization function.  The CRT will call all of these function | 
|  | 2207 | // pointers at start-up time and, eventually, at thread-creation time. | 
|  | 2208 | auto AddToXDU = [&CGM](llvm::Function *InitFunc) { | 
|  | 2209 | llvm::GlobalVariable *InitFuncPtr = new llvm::GlobalVariable( | 
|  | 2210 | CGM.getModule(), InitFunc->getType(), /*IsConstant=*/true, | 
|  | 2211 | llvm::GlobalVariable::InternalLinkage, InitFunc, | 
|  | 2212 | Twine(InitFunc->getName(), "$initializer$")); | 
|  | 2213 | InitFuncPtr->setSection(".CRT$XDU"); | 
|  | 2214 | // This variable has discardable linkage, we have to add it to @llvm.used to | 
|  | 2215 | // ensure it won't get discarded. | 
|  | 2216 | CGM.addUsedGlobal(InitFuncPtr); | 
|  | 2217 | return InitFuncPtr; | 
|  | 2218 | }; | 
|  | 2219 |  | 
|  | 2220 | std::vector<llvm::Function *> NonComdatInits; | 
|  | 2221 | for (size_t I = 0, E = CXXThreadLocalInitVars.size(); I != E; ++I) { | 
| Richard Smith | 5a99c49 | 2015-12-01 01:10:48 +0000 | [diff] [blame] | 2222 | llvm::GlobalVariable *GV = cast<llvm::GlobalVariable>( | 
|  | 2223 | CGM.GetGlobalValue(CGM.getMangledName(CXXThreadLocalInitVars[I]))); | 
| David Majnemer | b3341ea | 2014-10-05 05:05:40 +0000 | [diff] [blame] | 2224 | llvm::Function *F = CXXThreadLocalInits[I]; | 
|  | 2225 |  | 
|  | 2226 | // If the GV is already in a comdat group, then we have to join it. | 
| Rafael Espindola | 0d4fb98 | 2015-01-12 22:13:53 +0000 | [diff] [blame] | 2227 | if (llvm::Comdat *C = GV->getComdat()) | 
| David Majnemer | b3341ea | 2014-10-05 05:05:40 +0000 | [diff] [blame] | 2228 | AddToXDU(F)->setComdat(C); | 
| Rafael Espindola | 0d4fb98 | 2015-01-12 22:13:53 +0000 | [diff] [blame] | 2229 | else | 
| David Majnemer | b3341ea | 2014-10-05 05:05:40 +0000 | [diff] [blame] | 2230 | NonComdatInits.push_back(F); | 
| David Majnemer | b3341ea | 2014-10-05 05:05:40 +0000 | [diff] [blame] | 2231 | } | 
|  | 2232 |  | 
|  | 2233 | if (!NonComdatInits.empty()) { | 
|  | 2234 | llvm::FunctionType *FTy = | 
|  | 2235 | llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); | 
| Alexey Samsonov | 1444bb9 | 2014-10-17 00:20:19 +0000 | [diff] [blame] | 2236 | llvm::Function *InitFunc = CGM.CreateGlobalInitOrDestructFunction( | 
| Akira Hatanaka | 7791f1a4 | 2015-10-31 01:28:07 +0000 | [diff] [blame] | 2237 | FTy, "__tls_init", CGM.getTypes().arrangeNullaryFunction(), | 
|  | 2238 | SourceLocation(), /*TLS=*/true); | 
| David Majnemer | b3341ea | 2014-10-05 05:05:40 +0000 | [diff] [blame] | 2239 | CodeGenFunction(CGM).GenerateCXXGlobalInitFunc(InitFunc, NonComdatInits); | 
|  | 2240 |  | 
|  | 2241 | AddToXDU(InitFunc); | 
|  | 2242 | } | 
|  | 2243 | } | 
|  | 2244 |  | 
|  | 2245 | LValue MicrosoftCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, | 
|  | 2246 | const VarDecl *VD, | 
|  | 2247 | QualType LValType) { | 
|  | 2248 | CGF.CGM.ErrorUnsupported(VD, "thread wrappers"); | 
|  | 2249 | return LValue(); | 
|  | 2250 | } | 
|  | 2251 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2252 | static ConstantAddress getInitThreadEpochPtr(CodeGenModule &CGM) { | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2253 | StringRef VarName("_Init_thread_epoch"); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2254 | CharUnits Align = CGM.getIntAlign(); | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2255 | if (auto *GV = CGM.getModule().getNamedGlobal(VarName)) | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2256 | return ConstantAddress(GV, Align); | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2257 | auto *GV = new llvm::GlobalVariable( | 
|  | 2258 | CGM.getModule(), CGM.IntTy, | 
|  | 2259 | /*Constant=*/false, llvm::GlobalVariable::ExternalLinkage, | 
|  | 2260 | /*Initializer=*/nullptr, VarName, | 
|  | 2261 | /*InsertBefore=*/nullptr, llvm::GlobalVariable::GeneralDynamicTLSModel); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2262 | GV->setAlignment(Align.getQuantity()); | 
|  | 2263 | return ConstantAddress(GV, Align); | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2264 | } | 
|  | 2265 |  | 
|  | 2266 | static llvm::Constant *getInitThreadHeaderFn(CodeGenModule &CGM) { | 
|  | 2267 | llvm::FunctionType *FTy = | 
|  | 2268 | llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()), | 
|  | 2269 | CGM.IntTy->getPointerTo(), /*isVarArg=*/false); | 
|  | 2270 | return CGM.CreateRuntimeFunction( | 
|  | 2271 | FTy, "_Init_thread_header", | 
|  | 2272 | llvm::AttributeSet::get(CGM.getLLVMContext(), | 
|  | 2273 | llvm::AttributeSet::FunctionIndex, | 
|  | 2274 | llvm::Attribute::NoUnwind)); | 
|  | 2275 | } | 
|  | 2276 |  | 
|  | 2277 | static llvm::Constant *getInitThreadFooterFn(CodeGenModule &CGM) { | 
|  | 2278 | llvm::FunctionType *FTy = | 
|  | 2279 | llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()), | 
|  | 2280 | CGM.IntTy->getPointerTo(), /*isVarArg=*/false); | 
|  | 2281 | return CGM.CreateRuntimeFunction( | 
|  | 2282 | FTy, "_Init_thread_footer", | 
|  | 2283 | llvm::AttributeSet::get(CGM.getLLVMContext(), | 
|  | 2284 | llvm::AttributeSet::FunctionIndex, | 
|  | 2285 | llvm::Attribute::NoUnwind)); | 
|  | 2286 | } | 
|  | 2287 |  | 
|  | 2288 | static llvm::Constant *getInitThreadAbortFn(CodeGenModule &CGM) { | 
|  | 2289 | llvm::FunctionType *FTy = | 
|  | 2290 | llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()), | 
|  | 2291 | CGM.IntTy->getPointerTo(), /*isVarArg=*/false); | 
|  | 2292 | return CGM.CreateRuntimeFunction( | 
|  | 2293 | FTy, "_Init_thread_abort", | 
|  | 2294 | llvm::AttributeSet::get(CGM.getLLVMContext(), | 
|  | 2295 | llvm::AttributeSet::FunctionIndex, | 
|  | 2296 | llvm::Attribute::NoUnwind)); | 
|  | 2297 | } | 
|  | 2298 |  | 
|  | 2299 | namespace { | 
| David Blaikie | 7e70d68 | 2015-08-18 22:40:54 +0000 | [diff] [blame] | 2300 | struct ResetGuardBit final : EHScopeStack::Cleanup { | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2301 | Address Guard; | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2302 | unsigned GuardNum; | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2303 | ResetGuardBit(Address Guard, unsigned GuardNum) | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2304 | : Guard(Guard), GuardNum(GuardNum) {} | 
|  | 2305 |  | 
|  | 2306 | void Emit(CodeGenFunction &CGF, Flags flags) override { | 
|  | 2307 | // Reset the bit in the mask so that the static variable may be | 
|  | 2308 | // reinitialized. | 
|  | 2309 | CGBuilderTy &Builder = CGF.Builder; | 
|  | 2310 | llvm::LoadInst *LI = Builder.CreateLoad(Guard); | 
|  | 2311 | llvm::ConstantInt *Mask = | 
| Reid Kleckner | d16cebe | 2016-02-10 19:09:15 +0000 | [diff] [blame] | 2312 | llvm::ConstantInt::get(CGF.IntTy, ~(1ULL << GuardNum)); | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2313 | Builder.CreateStore(Builder.CreateAnd(LI, Mask), Guard); | 
|  | 2314 | } | 
|  | 2315 | }; | 
|  | 2316 |  | 
| David Blaikie | 7e70d68 | 2015-08-18 22:40:54 +0000 | [diff] [blame] | 2317 | struct CallInitThreadAbort final : EHScopeStack::Cleanup { | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2318 | llvm::Value *Guard; | 
|  | 2319 | CallInitThreadAbort(Address Guard) : Guard(Guard.getPointer()) {} | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2320 |  | 
|  | 2321 | void Emit(CodeGenFunction &CGF, Flags flags) override { | 
|  | 2322 | // Calling _Init_thread_abort will reset the guard's state. | 
|  | 2323 | CGF.EmitNounwindRuntimeCall(getInitThreadAbortFn(CGF.CGM), Guard); | 
|  | 2324 | } | 
|  | 2325 | }; | 
| Alexander Kornienko | ab9db51 | 2015-06-22 23:07:51 +0000 | [diff] [blame] | 2326 | } | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2327 |  | 
| John McCall | c84ed6a | 2012-05-01 06:13:13 +0000 | [diff] [blame] | 2328 | void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, | 
| Reid Kleckner | d8110b6 | 2013-09-10 20:14:30 +0000 | [diff] [blame] | 2329 | llvm::GlobalVariable *GV, | 
| John McCall | c84ed6a | 2012-05-01 06:13:13 +0000 | [diff] [blame] | 2330 | bool PerformInit) { | 
| Reid Kleckner | 563f0e8 | 2014-05-23 21:13:45 +0000 | [diff] [blame] | 2331 | // MSVC only uses guards for static locals. | 
|  | 2332 | if (!D.isStaticLocal()) { | 
|  | 2333 | assert(GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()); | 
|  | 2334 | // GlobalOpt is allowed to discard the initializer, so use linkonce_odr. | 
| Rafael Espindola | 77abc3a | 2015-01-16 16:04:45 +0000 | [diff] [blame] | 2335 | llvm::Function *F = CGF.CurFn; | 
|  | 2336 | F->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage); | 
|  | 2337 | F->setComdat(CGM.getModule().getOrInsertComdat(F->getName())); | 
| Reid Kleckner | 563f0e8 | 2014-05-23 21:13:45 +0000 | [diff] [blame] | 2338 | CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit); | 
|  | 2339 | return; | 
|  | 2340 | } | 
|  | 2341 |  | 
| David Majnemer | ec8e54b | 2015-05-07 21:19:06 +0000 | [diff] [blame] | 2342 | bool ThreadlocalStatic = D.getTLSKind(); | 
|  | 2343 | bool ThreadsafeStatic = getContext().getLangOpts().ThreadsafeStatics; | 
|  | 2344 |  | 
|  | 2345 | // Thread-safe static variables which aren't thread-specific have a | 
|  | 2346 | // per-variable guard. | 
|  | 2347 | bool HasPerVariableGuard = ThreadsafeStatic && !ThreadlocalStatic; | 
| Richard Smith | dbf74ba | 2013-04-14 23:01:42 +0000 | [diff] [blame] | 2348 |  | 
| Reid Kleckner | d8110b6 | 2013-09-10 20:14:30 +0000 | [diff] [blame] | 2349 | CGBuilderTy &Builder = CGF.Builder; | 
|  | 2350 | llvm::IntegerType *GuardTy = CGF.Int32Ty; | 
|  | 2351 | llvm::ConstantInt *Zero = llvm::ConstantInt::get(GuardTy, 0); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2352 | CharUnits GuardAlign = CharUnits::fromQuantity(4); | 
| Reid Kleckner | d8110b6 | 2013-09-10 20:14:30 +0000 | [diff] [blame] | 2353 |  | 
|  | 2354 | // Get the guard variable for this function if we have one already. | 
| David Majnemer | ec8e54b | 2015-05-07 21:19:06 +0000 | [diff] [blame] | 2355 | GuardInfo *GI = nullptr; | 
|  | 2356 | if (ThreadlocalStatic) | 
|  | 2357 | GI = &ThreadLocalGuardVariableMap[D.getDeclContext()]; | 
|  | 2358 | else if (!ThreadsafeStatic) | 
|  | 2359 | GI = &GuardVariableMap[D.getDeclContext()]; | 
|  | 2360 |  | 
|  | 2361 | llvm::GlobalVariable *GuardVar = GI ? GI->Guard : nullptr; | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2362 | unsigned GuardNum; | 
| David Majnemer | ec8e54b | 2015-05-07 21:19:06 +0000 | [diff] [blame] | 2363 | if (D.isExternallyVisible()) { | 
| Reid Kleckner | d8110b6 | 2013-09-10 20:14:30 +0000 | [diff] [blame] | 2364 | // Externally visible variables have to be numbered in Sema to properly | 
|  | 2365 | // handle unreachable VarDecls. | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2366 | GuardNum = getContext().getStaticLocalNumber(&D); | 
|  | 2367 | assert(GuardNum > 0); | 
|  | 2368 | GuardNum--; | 
|  | 2369 | } else if (HasPerVariableGuard) { | 
|  | 2370 | GuardNum = ThreadSafeGuardNumMap[D.getDeclContext()]++; | 
| Reid Kleckner | d8110b6 | 2013-09-10 20:14:30 +0000 | [diff] [blame] | 2371 | } else { | 
|  | 2372 | // Non-externally visible variables are numbered here in CodeGen. | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2373 | GuardNum = GI->BitIndex++; | 
| Reid Kleckner | d8110b6 | 2013-09-10 20:14:30 +0000 | [diff] [blame] | 2374 | } | 
|  | 2375 |  | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2376 | if (!HasPerVariableGuard && GuardNum >= 32) { | 
| Reid Kleckner | d8110b6 | 2013-09-10 20:14:30 +0000 | [diff] [blame] | 2377 | if (D.isExternallyVisible()) | 
|  | 2378 | ErrorUnsupportedABI(CGF, "more than 32 guarded initializations"); | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2379 | GuardNum %= 32; | 
|  | 2380 | GuardVar = nullptr; | 
| Reid Kleckner | d8110b6 | 2013-09-10 20:14:30 +0000 | [diff] [blame] | 2381 | } | 
|  | 2382 |  | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2383 | if (!GuardVar) { | 
| Reid Kleckner | d8110b6 | 2013-09-10 20:14:30 +0000 | [diff] [blame] | 2384 | // Mangle the name for the guard. | 
|  | 2385 | SmallString<256> GuardName; | 
|  | 2386 | { | 
|  | 2387 | llvm::raw_svector_ostream Out(GuardName); | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2388 | if (HasPerVariableGuard) | 
|  | 2389 | getMangleContext().mangleThreadSafeStaticGuardVariable(&D, GuardNum, | 
|  | 2390 | Out); | 
|  | 2391 | else | 
|  | 2392 | getMangleContext().mangleStaticGuardVariable(&D, Out); | 
| Reid Kleckner | d8110b6 | 2013-09-10 20:14:30 +0000 | [diff] [blame] | 2393 | } | 
|  | 2394 |  | 
| Hans Wennborg | ef2272c | 2014-06-18 15:55:13 +0000 | [diff] [blame] | 2395 | // Create the guard variable with a zero-initializer. Just absorb linkage, | 
|  | 2396 | // visibility and dll storage class from the guarded variable. | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2397 | GuardVar = | 
|  | 2398 | new llvm::GlobalVariable(CGM.getModule(), GuardTy, /*isConstant=*/false, | 
| Reid Kleckner | e9591b3 | 2014-04-23 18:22:11 +0000 | [diff] [blame] | 2399 | GV->getLinkage(), Zero, GuardName.str()); | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2400 | GuardVar->setVisibility(GV->getVisibility()); | 
|  | 2401 | GuardVar->setDLLStorageClass(GV->getDLLStorageClass()); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2402 | GuardVar->setAlignment(GuardAlign.getQuantity()); | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2403 | if (GuardVar->isWeakForLinker()) | 
|  | 2404 | GuardVar->setComdat( | 
|  | 2405 | CGM.getModule().getOrInsertComdat(GuardVar->getName())); | 
|  | 2406 | if (D.getTLSKind()) | 
|  | 2407 | GuardVar->setThreadLocal(true); | 
|  | 2408 | if (GI && !HasPerVariableGuard) | 
|  | 2409 | GI->Guard = GuardVar; | 
| Reid Kleckner | d8110b6 | 2013-09-10 20:14:30 +0000 | [diff] [blame] | 2410 | } | 
|  | 2411 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2412 | ConstantAddress GuardAddr(GuardVar, GuardAlign); | 
|  | 2413 |  | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2414 | assert(GuardVar->getLinkage() == GV->getLinkage() && | 
|  | 2415 | "static local from the same function had different linkage"); | 
| Reid Kleckner | d8110b6 | 2013-09-10 20:14:30 +0000 | [diff] [blame] | 2416 |  | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2417 | if (!HasPerVariableGuard) { | 
|  | 2418 | // Pseudo code for the test: | 
|  | 2419 | // if (!(GuardVar & MyGuardBit)) { | 
|  | 2420 | //   GuardVar |= MyGuardBit; | 
|  | 2421 | //   ... initialize the object ...; | 
|  | 2422 | // } | 
| Reid Kleckner | d8110b6 | 2013-09-10 20:14:30 +0000 | [diff] [blame] | 2423 |  | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2424 | // Test our bit from the guard variable. | 
| Aaron Ballman | abd466e | 2016-03-30 21:33:34 +0000 | [diff] [blame] | 2425 | llvm::ConstantInt *Bit = llvm::ConstantInt::get(GuardTy, 1ULL << GuardNum); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2426 | llvm::LoadInst *LI = Builder.CreateLoad(GuardAddr); | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2427 | llvm::Value *IsInitialized = | 
|  | 2428 | Builder.CreateICmpNE(Builder.CreateAnd(LI, Bit), Zero); | 
|  | 2429 | llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init"); | 
|  | 2430 | llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end"); | 
|  | 2431 | Builder.CreateCondBr(IsInitialized, EndBlock, InitBlock); | 
| Reid Kleckner | d8110b6 | 2013-09-10 20:14:30 +0000 | [diff] [blame] | 2432 |  | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2433 | // Set our bit in the guard variable and emit the initializer and add a global | 
|  | 2434 | // destructor if appropriate. | 
|  | 2435 | CGF.EmitBlock(InitBlock); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2436 | Builder.CreateStore(Builder.CreateOr(LI, Bit), GuardAddr); | 
|  | 2437 | CGF.EHStack.pushCleanup<ResetGuardBit>(EHCleanup, GuardAddr, GuardNum); | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2438 | CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit); | 
|  | 2439 | CGF.PopCleanupBlock(); | 
|  | 2440 | Builder.CreateBr(EndBlock); | 
|  | 2441 |  | 
|  | 2442 | // Continue. | 
|  | 2443 | CGF.EmitBlock(EndBlock); | 
|  | 2444 | } else { | 
|  | 2445 | // Pseudo code for the test: | 
|  | 2446 | // if (TSS > _Init_thread_epoch) { | 
|  | 2447 | //   _Init_thread_header(&TSS); | 
|  | 2448 | //   if (TSS == -1) { | 
|  | 2449 | //     ... initialize the object ...; | 
|  | 2450 | //     _Init_thread_footer(&TSS); | 
|  | 2451 | //   } | 
|  | 2452 | // } | 
|  | 2453 | // | 
|  | 2454 | // The algorithm is almost identical to what can be found in the appendix | 
|  | 2455 | // found in N2325. | 
|  | 2456 |  | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2457 | // This BasicBLock determines whether or not we have any work to do. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2458 | llvm::LoadInst *FirstGuardLoad = Builder.CreateLoad(GuardAddr); | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2459 | FirstGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered); | 
|  | 2460 | llvm::LoadInst *InitThreadEpoch = | 
|  | 2461 | Builder.CreateLoad(getInitThreadEpochPtr(CGM)); | 
|  | 2462 | llvm::Value *IsUninitialized = | 
|  | 2463 | Builder.CreateICmpSGT(FirstGuardLoad, InitThreadEpoch); | 
|  | 2464 | llvm::BasicBlock *AttemptInitBlock = CGF.createBasicBlock("init.attempt"); | 
|  | 2465 | llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end"); | 
|  | 2466 | Builder.CreateCondBr(IsUninitialized, AttemptInitBlock, EndBlock); | 
|  | 2467 |  | 
|  | 2468 | // This BasicBlock attempts to determine whether or not this thread is | 
|  | 2469 | // responsible for doing the initialization. | 
|  | 2470 | CGF.EmitBlock(AttemptInitBlock); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2471 | CGF.EmitNounwindRuntimeCall(getInitThreadHeaderFn(CGM), | 
|  | 2472 | GuardAddr.getPointer()); | 
|  | 2473 | llvm::LoadInst *SecondGuardLoad = Builder.CreateLoad(GuardAddr); | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2474 | SecondGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered); | 
|  | 2475 | llvm::Value *ShouldDoInit = | 
|  | 2476 | Builder.CreateICmpEQ(SecondGuardLoad, getAllOnesInt()); | 
|  | 2477 | llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init"); | 
|  | 2478 | Builder.CreateCondBr(ShouldDoInit, InitBlock, EndBlock); | 
|  | 2479 |  | 
|  | 2480 | // Ok, we ended up getting selected as the initializing thread. | 
|  | 2481 | CGF.EmitBlock(InitBlock); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2482 | CGF.EHStack.pushCleanup<CallInitThreadAbort>(EHCleanup, GuardAddr); | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2483 | CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit); | 
|  | 2484 | CGF.PopCleanupBlock(); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2485 | CGF.EmitNounwindRuntimeCall(getInitThreadFooterFn(CGM), | 
|  | 2486 | GuardAddr.getPointer()); | 
| David Majnemer | 8354eee | 2015-05-07 06:15:46 +0000 | [diff] [blame] | 2487 | Builder.CreateBr(EndBlock); | 
|  | 2488 |  | 
|  | 2489 | CGF.EmitBlock(EndBlock); | 
|  | 2490 | } | 
| John McCall | c84ed6a | 2012-05-01 06:13:13 +0000 | [diff] [blame] | 2491 | } | 
|  | 2492 |  | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2493 | bool MicrosoftCXXABI::isZeroInitializable(const MemberPointerType *MPT) { | 
|  | 2494 | // Null-ness for function memptrs only depends on the first field, which is | 
|  | 2495 | // the function pointer.  The rest don't matter, so we can zero initialize. | 
|  | 2496 | if (MPT->isMemberFunctionPointer()) | 
|  | 2497 | return true; | 
|  | 2498 |  | 
|  | 2499 | // The virtual base adjustment field is always -1 for null, so if we have one | 
|  | 2500 | // we can't zero initialize.  The field offset is sometimes also -1 if 0 is a | 
|  | 2501 | // valid field offset. | 
| David Majnemer | 1cdd96d | 2014-01-17 09:01:00 +0000 | [diff] [blame] | 2502 | const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); | 
|  | 2503 | MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 2504 | return (!MSInheritanceAttr::hasVBTableOffsetField(Inheritance) && | 
|  | 2505 | RD->nullFieldOffsetIsZero()); | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2506 | } | 
|  | 2507 |  | 
|  | 2508 | llvm::Type * | 
|  | 2509 | MicrosoftCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) { | 
| David Majnemer | 1cdd96d | 2014-01-17 09:01:00 +0000 | [diff] [blame] | 2510 | const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); | 
|  | 2511 | MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2512 | llvm::SmallVector<llvm::Type *, 4> fields; | 
|  | 2513 | if (MPT->isMemberFunctionPointer()) | 
|  | 2514 | fields.push_back(CGM.VoidPtrTy);  // FunctionPointerOrVirtualThunk | 
|  | 2515 | else | 
|  | 2516 | fields.push_back(CGM.IntTy);  // FieldOffset | 
|  | 2517 |  | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 2518 | if (MSInheritanceAttr::hasNVOffsetField(MPT->isMemberFunctionPointer(), | 
|  | 2519 | Inheritance)) | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2520 | fields.push_back(CGM.IntTy); | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 2521 | if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2522 | fields.push_back(CGM.IntTy); | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 2523 | if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance)) | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2524 | fields.push_back(CGM.IntTy);  // VirtualBaseAdjustmentOffset | 
|  | 2525 |  | 
|  | 2526 | if (fields.size() == 1) | 
|  | 2527 | return fields[0]; | 
|  | 2528 | return llvm::StructType::get(CGM.getLLVMContext(), fields); | 
|  | 2529 | } | 
|  | 2530 |  | 
|  | 2531 | void MicrosoftCXXABI:: | 
|  | 2532 | GetNullMemberPointerFields(const MemberPointerType *MPT, | 
|  | 2533 | llvm::SmallVectorImpl<llvm::Constant *> &fields) { | 
|  | 2534 | assert(fields.empty()); | 
| David Majnemer | 1cdd96d | 2014-01-17 09:01:00 +0000 | [diff] [blame] | 2535 | const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); | 
|  | 2536 | MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2537 | if (MPT->isMemberFunctionPointer()) { | 
|  | 2538 | // FunctionPointerOrVirtualThunk | 
|  | 2539 | fields.push_back(llvm::Constant::getNullValue(CGM.VoidPtrTy)); | 
|  | 2540 | } else { | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 2541 | if (RD->nullFieldOffsetIsZero()) | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2542 | fields.push_back(getZeroInt());  // FieldOffset | 
|  | 2543 | else | 
|  | 2544 | fields.push_back(getAllOnesInt());  // FieldOffset | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 2545 | } | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2546 |  | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 2547 | if (MSInheritanceAttr::hasNVOffsetField(MPT->isMemberFunctionPointer(), | 
|  | 2548 | Inheritance)) | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2549 | fields.push_back(getZeroInt()); | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 2550 | if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2551 | fields.push_back(getZeroInt()); | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 2552 | if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance)) | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2553 | fields.push_back(getAllOnesInt()); | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 2554 | } | 
|  | 2555 |  | 
|  | 2556 | llvm::Constant * | 
|  | 2557 | MicrosoftCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2558 | llvm::SmallVector<llvm::Constant *, 4> fields; | 
|  | 2559 | GetNullMemberPointerFields(MPT, fields); | 
|  | 2560 | if (fields.size() == 1) | 
|  | 2561 | return fields[0]; | 
|  | 2562 | llvm::Constant *Res = llvm::ConstantStruct::getAnon(fields); | 
|  | 2563 | assert(Res->getType() == ConvertMemberPointerType(MPT)); | 
|  | 2564 | return Res; | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 2565 | } | 
|  | 2566 |  | 
|  | 2567 | llvm::Constant * | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 2568 | MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField, | 
|  | 2569 | bool IsMemberFunction, | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 2570 | const CXXRecordDecl *RD, | 
| David Majnemer | e60813f | 2015-05-10 21:48:08 +0000 | [diff] [blame] | 2571 | CharUnits NonVirtualBaseAdjustment, | 
|  | 2572 | unsigned VBTableIndex) { | 
| David Majnemer | 1cdd96d | 2014-01-17 09:01:00 +0000 | [diff] [blame] | 2573 | MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 2574 |  | 
|  | 2575 | // Single inheritance class member pointer are represented as scalars instead | 
|  | 2576 | // of aggregates. | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 2577 | if (MSInheritanceAttr::hasOnlyOneField(IsMemberFunction, Inheritance)) | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 2578 | return FirstField; | 
|  | 2579 |  | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2580 | llvm::SmallVector<llvm::Constant *, 4> fields; | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 2581 | fields.push_back(FirstField); | 
|  | 2582 |  | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 2583 | if (MSInheritanceAttr::hasNVOffsetField(IsMemberFunction, Inheritance)) | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 2584 | fields.push_back(llvm::ConstantInt::get( | 
|  | 2585 | CGM.IntTy, NonVirtualBaseAdjustment.getQuantity())); | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 2586 |  | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 2587 | if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) { | 
| Reid Kleckner | aec4409 | 2013-10-15 01:18:02 +0000 | [diff] [blame] | 2588 | CharUnits Offs = CharUnits::Zero(); | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 2589 | if (VBTableIndex) | 
| Reid Kleckner | 5b1b5d5 | 2014-01-14 00:50:39 +0000 | [diff] [blame] | 2590 | Offs = getContext().getASTRecordLayout(RD).getVBPtrOffset(); | 
| Reid Kleckner | aec4409 | 2013-10-15 01:18:02 +0000 | [diff] [blame] | 2591 | fields.push_back(llvm::ConstantInt::get(CGM.IntTy, Offs.getQuantity())); | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2592 | } | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 2593 |  | 
|  | 2594 | // The rest of the fields are adjusted by conversions to a more derived class. | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 2595 | if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance)) | 
| David Majnemer | e60813f | 2015-05-10 21:48:08 +0000 | [diff] [blame] | 2596 | fields.push_back(llvm::ConstantInt::get(CGM.IntTy, VBTableIndex)); | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 2597 |  | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2598 | return llvm::ConstantStruct::getAnon(fields); | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 2599 | } | 
|  | 2600 |  | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 2601 | llvm::Constant * | 
|  | 2602 | MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, | 
|  | 2603 | CharUnits offset) { | 
| David Majnemer | 1cdd96d | 2014-01-17 09:01:00 +0000 | [diff] [blame] | 2604 | const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 2605 | if (RD->getMSInheritanceModel() == | 
|  | 2606 | MSInheritanceAttr::Keyword_virtual_inheritance) | 
| David Majnemer | 08ef2ba | 2015-06-23 20:34:18 +0000 | [diff] [blame] | 2607 | offset -= getContext().getOffsetOfBaseWithVBPtr(RD); | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 2608 | llvm::Constant *FirstField = | 
|  | 2609 | llvm::ConstantInt::get(CGM.IntTy, offset.getQuantity()); | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 2610 | return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/false, RD, | 
| David Majnemer | e60813f | 2015-05-10 21:48:08 +0000 | [diff] [blame] | 2611 | CharUnits::Zero(), /*VBTableIndex=*/0); | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 2612 | } | 
|  | 2613 |  | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 2614 | llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const APValue &MP, | 
|  | 2615 | QualType MPType) { | 
| David Majnemer | 5ca193c | 2015-06-23 07:31:07 +0000 | [diff] [blame] | 2616 | const MemberPointerType *DstTy = MPType->castAs<MemberPointerType>(); | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 2617 | const ValueDecl *MPD = MP.getMemberPointerDecl(); | 
|  | 2618 | if (!MPD) | 
| David Majnemer | 5ca193c | 2015-06-23 07:31:07 +0000 | [diff] [blame] | 2619 | return EmitNullMemberPointer(DstTy); | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 2620 |  | 
| David Majnemer | 5ca193c | 2015-06-23 07:31:07 +0000 | [diff] [blame] | 2621 | ASTContext &Ctx = getContext(); | 
|  | 2622 | ArrayRef<const CXXRecordDecl *> MemberPointerPath = MP.getMemberPointerPath(); | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 2623 |  | 
| David Majnemer | 5ca193c | 2015-06-23 07:31:07 +0000 | [diff] [blame] | 2624 | llvm::Constant *C; | 
|  | 2625 | if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) { | 
|  | 2626 | C = EmitMemberFunctionPointer(MD); | 
|  | 2627 | } else { | 
|  | 2628 | CharUnits FieldOffset = Ctx.toCharUnitsFromBits(Ctx.getFieldOffset(MPD)); | 
|  | 2629 | C = EmitMemberDataPointer(DstTy, FieldOffset); | 
|  | 2630 | } | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 2631 |  | 
| David Majnemer | 5ca193c | 2015-06-23 07:31:07 +0000 | [diff] [blame] | 2632 | if (!MemberPointerPath.empty()) { | 
|  | 2633 | const CXXRecordDecl *SrcRD = cast<CXXRecordDecl>(MPD->getDeclContext()); | 
|  | 2634 | const Type *SrcRecTy = Ctx.getTypeDeclType(SrcRD).getTypePtr(); | 
|  | 2635 | const MemberPointerType *SrcTy = | 
|  | 2636 | Ctx.getMemberPointerType(DstTy->getPointeeType(), SrcRecTy) | 
|  | 2637 | ->castAs<MemberPointerType>(); | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 2638 |  | 
| David Majnemer | 5ca193c | 2015-06-23 07:31:07 +0000 | [diff] [blame] | 2639 | bool DerivedMember = MP.isMemberPointerToDerivedMember(); | 
|  | 2640 | SmallVector<const CXXBaseSpecifier *, 4> DerivedToBasePath; | 
|  | 2641 | const CXXRecordDecl *PrevRD = SrcRD; | 
|  | 2642 | for (const CXXRecordDecl *PathElem : MemberPointerPath) { | 
|  | 2643 | const CXXRecordDecl *Base = nullptr; | 
|  | 2644 | const CXXRecordDecl *Derived = nullptr; | 
|  | 2645 | if (DerivedMember) { | 
|  | 2646 | Base = PathElem; | 
|  | 2647 | Derived = PrevRD; | 
|  | 2648 | } else { | 
|  | 2649 | Base = PrevRD; | 
|  | 2650 | Derived = PathElem; | 
|  | 2651 | } | 
|  | 2652 | for (const CXXBaseSpecifier &BS : Derived->bases()) | 
|  | 2653 | if (BS.getType()->getAsCXXRecordDecl()->getCanonicalDecl() == | 
|  | 2654 | Base->getCanonicalDecl()) | 
|  | 2655 | DerivedToBasePath.push_back(&BS); | 
|  | 2656 | PrevRD = PathElem; | 
|  | 2657 | } | 
|  | 2658 | assert(DerivedToBasePath.size() == MemberPointerPath.size()); | 
|  | 2659 |  | 
|  | 2660 | CastKind CK = DerivedMember ? CK_DerivedToBaseMemberPointer | 
|  | 2661 | : CK_BaseToDerivedMemberPointer; | 
|  | 2662 | C = EmitMemberPointerConversion(SrcTy, DstTy, CK, DerivedToBasePath.begin(), | 
|  | 2663 | DerivedToBasePath.end(), C); | 
|  | 2664 | } | 
|  | 2665 | return C; | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 2666 | } | 
|  | 2667 |  | 
|  | 2668 | llvm::Constant * | 
| David Majnemer | 5ca193c | 2015-06-23 07:31:07 +0000 | [diff] [blame] | 2669 | MicrosoftCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 2670 | assert(MD->isInstance() && "Member function must not be static!"); | 
| David Majnemer | 5ca193c | 2015-06-23 07:31:07 +0000 | [diff] [blame] | 2671 |  | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 2672 | MD = MD->getCanonicalDecl(); | 
| David Majnemer | 5ca193c | 2015-06-23 07:31:07 +0000 | [diff] [blame] | 2673 | CharUnits NonVirtualBaseAdjustment = CharUnits::Zero(); | 
|  | 2674 | const CXXRecordDecl *RD = MD->getParent()->getMostRecentDecl(); | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 2675 | CodeGenTypes &Types = CGM.getTypes(); | 
|  | 2676 |  | 
| David Majnemer | e60813f | 2015-05-10 21:48:08 +0000 | [diff] [blame] | 2677 | unsigned VBTableIndex = 0; | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 2678 | llvm::Constant *FirstField; | 
| Reid Kleckner | c347351 | 2014-08-29 21:43:29 +0000 | [diff] [blame] | 2679 | const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); | 
| Hans Wennborg | 88497d6 | 2013-11-15 17:24:45 +0000 | [diff] [blame] | 2680 | if (!MD->isVirtual()) { | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 2681 | llvm::Type *Ty; | 
|  | 2682 | // Check whether the function has a computable LLVM signature. | 
|  | 2683 | if (Types.isFuncTypeConvertible(FPT)) { | 
|  | 2684 | // The function has a computable LLVM signature; use the correct type. | 
|  | 2685 | Ty = Types.GetFunctionType(Types.arrangeCXXMethodDeclaration(MD)); | 
|  | 2686 | } else { | 
|  | 2687 | // Use an arbitrary non-function type to tell GetAddrOfFunction that the | 
|  | 2688 | // function type is incomplete. | 
|  | 2689 | Ty = CGM.PtrDiffTy; | 
|  | 2690 | } | 
|  | 2691 | FirstField = CGM.GetAddrOfFunction(MD, Ty); | 
| Hans Wennborg | 88497d6 | 2013-11-15 17:24:45 +0000 | [diff] [blame] | 2692 | } else { | 
| David Majnemer | e0e228a | 2015-06-11 08:12:44 +0000 | [diff] [blame] | 2693 | auto &VTableContext = CGM.getMicrosoftVTableContext(); | 
|  | 2694 | MicrosoftVTableContext::MethodVFTableLocation ML = | 
|  | 2695 | VTableContext.getMethodVFTableLocation(MD); | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 2696 | FirstField = EmitVirtualMemPtrThunk(MD, ML); | 
| David Majnemer | e0e228a | 2015-06-11 08:12:44 +0000 | [diff] [blame] | 2697 | // Include the vfptr adjustment if the method is in a non-primary vftable. | 
|  | 2698 | NonVirtualBaseAdjustment += ML.VFPtrOffset; | 
|  | 2699 | if (ML.VBase) | 
|  | 2700 | VBTableIndex = VTableContext.getVBTableIndex(RD, ML.VBase) * 4; | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 2701 | } | 
|  | 2702 |  | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 2703 | if (VBTableIndex == 0 && | 
|  | 2704 | RD->getMSInheritanceModel() == | 
|  | 2705 | MSInheritanceAttr::Keyword_virtual_inheritance) | 
| David Majnemer | 08ef2ba | 2015-06-23 20:34:18 +0000 | [diff] [blame] | 2706 | NonVirtualBaseAdjustment -= getContext().getOffsetOfBaseWithVBPtr(RD); | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 2707 |  | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 2708 | // The rest of the fields are common with data member pointers. | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 2709 | FirstField = llvm::ConstantExpr::getBitCast(FirstField, CGM.VoidPtrTy); | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 2710 | return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/true, RD, | 
| David Majnemer | e60813f | 2015-05-10 21:48:08 +0000 | [diff] [blame] | 2711 | NonVirtualBaseAdjustment, VBTableIndex); | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 2712 | } | 
|  | 2713 |  | 
| Reid Kleckner | 700c3ee | 2013-04-30 20:15:14 +0000 | [diff] [blame] | 2714 | /// Member pointers are the same if they're either bitwise identical *or* both | 
|  | 2715 | /// null.  Null-ness for function members is determined by the first field, | 
|  | 2716 | /// while for data member pointers we must compare all fields. | 
|  | 2717 | llvm::Value * | 
|  | 2718 | MicrosoftCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF, | 
|  | 2719 | llvm::Value *L, | 
|  | 2720 | llvm::Value *R, | 
|  | 2721 | const MemberPointerType *MPT, | 
|  | 2722 | bool Inequality) { | 
|  | 2723 | CGBuilderTy &Builder = CGF.Builder; | 
|  | 2724 |  | 
|  | 2725 | // Handle != comparisons by switching the sense of all boolean operations. | 
|  | 2726 | llvm::ICmpInst::Predicate Eq; | 
|  | 2727 | llvm::Instruction::BinaryOps And, Or; | 
|  | 2728 | if (Inequality) { | 
|  | 2729 | Eq = llvm::ICmpInst::ICMP_NE; | 
|  | 2730 | And = llvm::Instruction::Or; | 
|  | 2731 | Or = llvm::Instruction::And; | 
|  | 2732 | } else { | 
|  | 2733 | Eq = llvm::ICmpInst::ICMP_EQ; | 
|  | 2734 | And = llvm::Instruction::And; | 
|  | 2735 | Or = llvm::Instruction::Or; | 
|  | 2736 | } | 
|  | 2737 |  | 
|  | 2738 | // If this is a single field member pointer (single inheritance), this is a | 
|  | 2739 | // single icmp. | 
| David Majnemer | 1cdd96d | 2014-01-17 09:01:00 +0000 | [diff] [blame] | 2740 | const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); | 
|  | 2741 | MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 2742 | if (MSInheritanceAttr::hasOnlyOneField(MPT->isMemberFunctionPointer(), | 
|  | 2743 | Inheritance)) | 
| Reid Kleckner | 700c3ee | 2013-04-30 20:15:14 +0000 | [diff] [blame] | 2744 | return Builder.CreateICmp(Eq, L, R); | 
|  | 2745 |  | 
|  | 2746 | // Compare the first field. | 
|  | 2747 | llvm::Value *L0 = Builder.CreateExtractValue(L, 0, "lhs.0"); | 
|  | 2748 | llvm::Value *R0 = Builder.CreateExtractValue(R, 0, "rhs.0"); | 
|  | 2749 | llvm::Value *Cmp0 = Builder.CreateICmp(Eq, L0, R0, "memptr.cmp.first"); | 
|  | 2750 |  | 
|  | 2751 | // Compare everything other than the first field. | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 2752 | llvm::Value *Res = nullptr; | 
| Reid Kleckner | 700c3ee | 2013-04-30 20:15:14 +0000 | [diff] [blame] | 2753 | llvm::StructType *LType = cast<llvm::StructType>(L->getType()); | 
|  | 2754 | for (unsigned I = 1, E = LType->getNumElements(); I != E; ++I) { | 
|  | 2755 | llvm::Value *LF = Builder.CreateExtractValue(L, I); | 
|  | 2756 | llvm::Value *RF = Builder.CreateExtractValue(R, I); | 
|  | 2757 | llvm::Value *Cmp = Builder.CreateICmp(Eq, LF, RF, "memptr.cmp.rest"); | 
|  | 2758 | if (Res) | 
|  | 2759 | Res = Builder.CreateBinOp(And, Res, Cmp); | 
|  | 2760 | else | 
|  | 2761 | Res = Cmp; | 
|  | 2762 | } | 
|  | 2763 |  | 
|  | 2764 | // Check if the first field is 0 if this is a function pointer. | 
|  | 2765 | if (MPT->isMemberFunctionPointer()) { | 
|  | 2766 | // (l1 == r1 && ...) || l0 == 0 | 
|  | 2767 | llvm::Value *Zero = llvm::Constant::getNullValue(L0->getType()); | 
|  | 2768 | llvm::Value *IsZero = Builder.CreateICmp(Eq, L0, Zero, "memptr.cmp.iszero"); | 
|  | 2769 | Res = Builder.CreateBinOp(Or, Res, IsZero); | 
|  | 2770 | } | 
|  | 2771 |  | 
|  | 2772 | // Combine the comparison of the first field, which must always be true for | 
|  | 2773 | // this comparison to succeeed. | 
|  | 2774 | return Builder.CreateBinOp(And, Res, Cmp0, "memptr.cmp"); | 
|  | 2775 | } | 
|  | 2776 |  | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 2777 | llvm::Value * | 
|  | 2778 | MicrosoftCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF, | 
|  | 2779 | llvm::Value *MemPtr, | 
|  | 2780 | const MemberPointerType *MPT) { | 
|  | 2781 | CGBuilderTy &Builder = CGF.Builder; | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2782 | llvm::SmallVector<llvm::Constant *, 4> fields; | 
|  | 2783 | // We only need one field for member functions. | 
|  | 2784 | if (MPT->isMemberFunctionPointer()) | 
|  | 2785 | fields.push_back(llvm::Constant::getNullValue(CGM.VoidPtrTy)); | 
|  | 2786 | else | 
|  | 2787 | GetNullMemberPointerFields(MPT, fields); | 
|  | 2788 | assert(!fields.empty()); | 
|  | 2789 | llvm::Value *FirstField = MemPtr; | 
|  | 2790 | if (MemPtr->getType()->isStructTy()) | 
|  | 2791 | FirstField = Builder.CreateExtractValue(MemPtr, 0); | 
|  | 2792 | llvm::Value *Res = Builder.CreateICmpNE(FirstField, fields[0], "memptr.cmp0"); | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 2793 |  | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2794 | // For function member pointers, we only need to test the function pointer | 
|  | 2795 | // field.  The other fields if any can be garbage. | 
|  | 2796 | if (MPT->isMemberFunctionPointer()) | 
|  | 2797 | return Res; | 
|  | 2798 |  | 
|  | 2799 | // Otherwise, emit a series of compares and combine the results. | 
|  | 2800 | for (int I = 1, E = fields.size(); I < E; ++I) { | 
|  | 2801 | llvm::Value *Field = Builder.CreateExtractValue(MemPtr, I); | 
|  | 2802 | llvm::Value *Next = Builder.CreateICmpNE(Field, fields[I], "memptr.cmp"); | 
| Reid Kleckner | 34a38d8 | 2014-05-02 00:05:16 +0000 | [diff] [blame] | 2803 | Res = Builder.CreateOr(Res, Next, "memptr.tobool"); | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2804 | } | 
|  | 2805 | return Res; | 
|  | 2806 | } | 
|  | 2807 |  | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 2808 | bool MicrosoftCXXABI::MemberPointerConstantIsNull(const MemberPointerType *MPT, | 
|  | 2809 | llvm::Constant *Val) { | 
|  | 2810 | // Function pointers are null if the pointer in the first field is null. | 
|  | 2811 | if (MPT->isMemberFunctionPointer()) { | 
|  | 2812 | llvm::Constant *FirstField = Val->getType()->isStructTy() ? | 
|  | 2813 | Val->getAggregateElement(0U) : Val; | 
|  | 2814 | return FirstField->isNullValue(); | 
|  | 2815 | } | 
|  | 2816 |  | 
|  | 2817 | // If it's not a function pointer and it's zero initializable, we can easily | 
|  | 2818 | // check zero. | 
|  | 2819 | if (isZeroInitializable(MPT) && Val->isNullValue()) | 
|  | 2820 | return true; | 
|  | 2821 |  | 
|  | 2822 | // Otherwise, break down all the fields for comparison.  Hopefully these | 
|  | 2823 | // little Constants are reused, while a big null struct might not be. | 
|  | 2824 | llvm::SmallVector<llvm::Constant *, 4> Fields; | 
|  | 2825 | GetNullMemberPointerFields(MPT, Fields); | 
|  | 2826 | if (Fields.size() == 1) { | 
|  | 2827 | assert(Val->getType()->isIntegerTy()); | 
|  | 2828 | return Val == Fields[0]; | 
|  | 2829 | } | 
|  | 2830 |  | 
|  | 2831 | unsigned I, E; | 
|  | 2832 | for (I = 0, E = Fields.size(); I != E; ++I) { | 
|  | 2833 | if (Val->getAggregateElement(I) != Fields[I]) | 
|  | 2834 | break; | 
|  | 2835 | } | 
|  | 2836 | return I == E; | 
|  | 2837 | } | 
|  | 2838 |  | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 2839 | llvm::Value * | 
|  | 2840 | MicrosoftCXXABI::GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2841 | Address This, | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 2842 | llvm::Value *VBPtrOffset, | 
| Timur Iskhodzhanov | 07e6eff | 2013-10-27 17:10:27 +0000 | [diff] [blame] | 2843 | llvm::Value *VBTableOffset, | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 2844 | llvm::Value **VBPtrOut) { | 
|  | 2845 | CGBuilderTy &Builder = CGF.Builder; | 
|  | 2846 | // Load the vbtable pointer from the vbptr in the instance. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2847 | This = Builder.CreateElementBitCast(This, CGM.Int8Ty); | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 2848 | llvm::Value *VBPtr = | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2849 | Builder.CreateInBoundsGEP(This.getPointer(), VBPtrOffset, "vbptr"); | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 2850 | if (VBPtrOut) *VBPtrOut = VBPtr; | 
| Reid Kleckner | 0ba8ba4 | 2014-10-22 17:26:00 +0000 | [diff] [blame] | 2851 | VBPtr = Builder.CreateBitCast(VBPtr, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2852 | CGM.Int32Ty->getPointerTo(0)->getPointerTo(This.getAddressSpace())); | 
|  | 2853 |  | 
|  | 2854 | CharUnits VBPtrAlign; | 
|  | 2855 | if (auto CI = dyn_cast<llvm::ConstantInt>(VBPtrOffset)) { | 
|  | 2856 | VBPtrAlign = This.getAlignment().alignmentAtOffset( | 
|  | 2857 | CharUnits::fromQuantity(CI->getSExtValue())); | 
|  | 2858 | } else { | 
|  | 2859 | VBPtrAlign = CGF.getPointerAlign(); | 
|  | 2860 | } | 
|  | 2861 |  | 
|  | 2862 | llvm::Value *VBTable = Builder.CreateAlignedLoad(VBPtr, VBPtrAlign, "vbtable"); | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 2863 |  | 
| Reid Kleckner | 0ba8ba4 | 2014-10-22 17:26:00 +0000 | [diff] [blame] | 2864 | // Translate from byte offset to table index. It improves analyzability. | 
|  | 2865 | llvm::Value *VBTableIndex = Builder.CreateAShr( | 
|  | 2866 | VBTableOffset, llvm::ConstantInt::get(VBTableOffset->getType(), 2), | 
|  | 2867 | "vbtindex", /*isExact=*/true); | 
|  | 2868 |  | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 2869 | // Load an i32 offset from the vb-table. | 
| Reid Kleckner | 0ba8ba4 | 2014-10-22 17:26:00 +0000 | [diff] [blame] | 2870 | llvm::Value *VBaseOffs = Builder.CreateInBoundsGEP(VBTable, VBTableIndex); | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 2871 | VBaseOffs = Builder.CreateBitCast(VBaseOffs, CGM.Int32Ty->getPointerTo(0)); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2872 | return Builder.CreateAlignedLoad(VBaseOffs, CharUnits::fromQuantity(4), | 
|  | 2873 | "vbase_offs"); | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 2874 | } | 
|  | 2875 |  | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2876 | // Returns an adjusted base cast to i8*, since we do more address arithmetic on | 
|  | 2877 | // it. | 
| David Majnemer | 2b0d66d | 2014-02-20 23:22:07 +0000 | [diff] [blame] | 2878 | llvm::Value *MicrosoftCXXABI::AdjustVirtualBase( | 
|  | 2879 | CodeGenFunction &CGF, const Expr *E, const CXXRecordDecl *RD, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2880 | Address Base, llvm::Value *VBTableOffset, llvm::Value *VBPtrOffset) { | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2881 | CGBuilderTy &Builder = CGF.Builder; | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2882 | Base = Builder.CreateElementBitCast(Base, CGM.Int8Ty); | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 2883 | llvm::BasicBlock *OriginalBB = nullptr; | 
|  | 2884 | llvm::BasicBlock *SkipAdjustBB = nullptr; | 
|  | 2885 | llvm::BasicBlock *VBaseAdjustBB = nullptr; | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2886 |  | 
|  | 2887 | // In the unspecified inheritance model, there might not be a vbtable at all, | 
|  | 2888 | // in which case we need to skip the virtual base lookup.  If there is a | 
|  | 2889 | // vbtable, the first entry is a no-op entry that gives back the original | 
|  | 2890 | // base, so look for a virtual base adjustment offset of zero. | 
|  | 2891 | if (VBPtrOffset) { | 
|  | 2892 | OriginalBB = Builder.GetInsertBlock(); | 
|  | 2893 | VBaseAdjustBB = CGF.createBasicBlock("memptr.vadjust"); | 
|  | 2894 | SkipAdjustBB = CGF.createBasicBlock("memptr.skip_vadjust"); | 
|  | 2895 | llvm::Value *IsVirtual = | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 2896 | Builder.CreateICmpNE(VBTableOffset, getZeroInt(), | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2897 | "memptr.is_vbase"); | 
|  | 2898 | Builder.CreateCondBr(IsVirtual, VBaseAdjustBB, SkipAdjustBB); | 
|  | 2899 | CGF.EmitBlock(VBaseAdjustBB); | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 2900 | } | 
|  | 2901 |  | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2902 | // If we weren't given a dynamic vbptr offset, RD should be complete and we'll | 
|  | 2903 | // know the vbptr offset. | 
|  | 2904 | if (!VBPtrOffset) { | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 2905 | CharUnits offs = CharUnits::Zero(); | 
| David Majnemer | 2b0d66d | 2014-02-20 23:22:07 +0000 | [diff] [blame] | 2906 | if (!RD->hasDefinition()) { | 
|  | 2907 | DiagnosticsEngine &Diags = CGF.CGM.getDiags(); | 
|  | 2908 | unsigned DiagID = Diags.getCustomDiagID( | 
|  | 2909 | DiagnosticsEngine::Error, | 
|  | 2910 | "member pointer representation requires a " | 
|  | 2911 | "complete class type for %0 to perform this expression"); | 
|  | 2912 | Diags.Report(E->getExprLoc(), DiagID) << RD << E->getSourceRange(); | 
|  | 2913 | } else if (RD->getNumVBases()) | 
| Reid Kleckner | 5b1b5d5 | 2014-01-14 00:50:39 +0000 | [diff] [blame] | 2914 | offs = getContext().getASTRecordLayout(RD).getVBPtrOffset(); | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2915 | VBPtrOffset = llvm::ConstantInt::get(CGM.IntTy, offs.getQuantity()); | 
|  | 2916 | } | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 2917 | llvm::Value *VBPtr = nullptr; | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2918 | llvm::Value *VBaseOffs = | 
| Timur Iskhodzhanov | 07e6eff | 2013-10-27 17:10:27 +0000 | [diff] [blame] | 2919 | GetVBaseOffsetFromVBPtr(CGF, Base, VBPtrOffset, VBTableOffset, &VBPtr); | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2920 | llvm::Value *AdjustedBase = Builder.CreateInBoundsGEP(VBPtr, VBaseOffs); | 
|  | 2921 |  | 
|  | 2922 | // Merge control flow with the case where we didn't have to adjust. | 
|  | 2923 | if (VBaseAdjustBB) { | 
|  | 2924 | Builder.CreateBr(SkipAdjustBB); | 
|  | 2925 | CGF.EmitBlock(SkipAdjustBB); | 
|  | 2926 | llvm::PHINode *Phi = Builder.CreatePHI(CGM.Int8PtrTy, 2, "memptr.base"); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2927 | Phi->addIncoming(Base.getPointer(), OriginalBB); | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2928 | Phi->addIncoming(AdjustedBase, VBaseAdjustBB); | 
|  | 2929 | return Phi; | 
|  | 2930 | } | 
|  | 2931 | return AdjustedBase; | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 2932 | } | 
|  | 2933 |  | 
| David Majnemer | 2b0d66d | 2014-02-20 23:22:07 +0000 | [diff] [blame] | 2934 | llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress( | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2935 | CodeGenFunction &CGF, const Expr *E, Address Base, llvm::Value *MemPtr, | 
| David Majnemer | 2b0d66d | 2014-02-20 23:22:07 +0000 | [diff] [blame] | 2936 | const MemberPointerType *MPT) { | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2937 | assert(MPT->isMemberDataPointer()); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2938 | unsigned AS = Base.getAddressSpace(); | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 2939 | llvm::Type *PType = | 
|  | 2940 | CGF.ConvertTypeForMem(MPT->getPointeeType())->getPointerTo(AS); | 
|  | 2941 | CGBuilderTy &Builder = CGF.Builder; | 
| David Majnemer | 1cdd96d | 2014-01-17 09:01:00 +0000 | [diff] [blame] | 2942 | const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); | 
|  | 2943 | MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 2944 |  | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2945 | // Extract the fields we need, regardless of model.  We'll apply them if we | 
|  | 2946 | // have them. | 
|  | 2947 | llvm::Value *FieldOffset = MemPtr; | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 2948 | llvm::Value *VirtualBaseAdjustmentOffset = nullptr; | 
|  | 2949 | llvm::Value *VBPtrOffset = nullptr; | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2950 | if (MemPtr->getType()->isStructTy()) { | 
|  | 2951 | // We need to extract values. | 
|  | 2952 | unsigned I = 0; | 
|  | 2953 | FieldOffset = Builder.CreateExtractValue(MemPtr, I++); | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 2954 | if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2955 | VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++); | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 2956 | if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance)) | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2957 | VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++); | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 2958 | } | 
|  | 2959 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2960 | llvm::Value *Addr; | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2961 | if (VirtualBaseAdjustmentOffset) { | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2962 | Addr = AdjustVirtualBase(CGF, E, RD, Base, VirtualBaseAdjustmentOffset, | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 2963 | VBPtrOffset); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2964 | } else { | 
|  | 2965 | Addr = Base.getPointer(); | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 2966 | } | 
| Reid Kleckner | ae94512 | 2013-12-05 22:44:07 +0000 | [diff] [blame] | 2967 |  | 
|  | 2968 | // Cast to char*. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2969 | Addr = Builder.CreateBitCast(Addr, CGF.Int8Ty->getPointerTo(AS)); | 
| Reid Kleckner | ae94512 | 2013-12-05 22:44:07 +0000 | [diff] [blame] | 2970 |  | 
|  | 2971 | // Apply the offset, which we assume is non-null. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2972 | Addr = Builder.CreateInBoundsGEP(Addr, FieldOffset, "memptr.offset"); | 
| Reid Kleckner | 407e8b6 | 2013-03-22 19:02:54 +0000 | [diff] [blame] | 2973 |  | 
|  | 2974 | // Cast the address to the appropriate pointer type, adopting the address | 
|  | 2975 | // space of the base pointer. | 
|  | 2976 | return Builder.CreateBitCast(Addr, PType); | 
|  | 2977 | } | 
|  | 2978 |  | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 2979 | llvm::Value * | 
|  | 2980 | MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, | 
|  | 2981 | const CastExpr *E, | 
|  | 2982 | llvm::Value *Src) { | 
|  | 2983 | assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || | 
|  | 2984 | E->getCastKind() == CK_BaseToDerivedMemberPointer || | 
|  | 2985 | E->getCastKind() == CK_ReinterpretMemberPointer); | 
|  | 2986 |  | 
|  | 2987 | // Use constant emission if we can. | 
|  | 2988 | if (isa<llvm::Constant>(Src)) | 
|  | 2989 | return EmitMemberPointerConversion(E, cast<llvm::Constant>(Src)); | 
|  | 2990 |  | 
|  | 2991 | // We may be adding or dropping fields from the member pointer, so we need | 
|  | 2992 | // both types and the inheritance models of both records. | 
|  | 2993 | const MemberPointerType *SrcTy = | 
|  | 2994 | E->getSubExpr()->getType()->castAs<MemberPointerType>(); | 
|  | 2995 | const MemberPointerType *DstTy = E->getType()->castAs<MemberPointerType>(); | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 2996 | bool IsFunc = SrcTy->isMemberFunctionPointer(); | 
|  | 2997 |  | 
|  | 2998 | // If the classes use the same null representation, reinterpret_cast is a nop. | 
|  | 2999 | bool IsReinterpret = E->getCastKind() == CK_ReinterpretMemberPointer; | 
| David Majnemer | 1cdd96d | 2014-01-17 09:01:00 +0000 | [diff] [blame] | 3000 | if (IsReinterpret && IsFunc) | 
|  | 3001 | return Src; | 
|  | 3002 |  | 
|  | 3003 | CXXRecordDecl *SrcRD = SrcTy->getMostRecentCXXRecordDecl(); | 
|  | 3004 | CXXRecordDecl *DstRD = DstTy->getMostRecentCXXRecordDecl(); | 
|  | 3005 | if (IsReinterpret && | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 3006 | SrcRD->nullFieldOffsetIsZero() == DstRD->nullFieldOffsetIsZero()) | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 3007 | return Src; | 
|  | 3008 |  | 
|  | 3009 | CGBuilderTy &Builder = CGF.Builder; | 
|  | 3010 |  | 
|  | 3011 | // Branch past the conversion if Src is null. | 
|  | 3012 | llvm::Value *IsNotNull = EmitMemberPointerIsNotNull(CGF, Src, SrcTy); | 
|  | 3013 | llvm::Constant *DstNull = EmitNullMemberPointer(DstTy); | 
|  | 3014 |  | 
|  | 3015 | // C++ 5.2.10p9: The null member pointer value is converted to the null member | 
|  | 3016 | //   pointer value of the destination type. | 
|  | 3017 | if (IsReinterpret) { | 
|  | 3018 | // For reinterpret casts, sema ensures that src and dst are both functions | 
|  | 3019 | // or data and have the same size, which means the LLVM types should match. | 
|  | 3020 | assert(Src->getType() == DstNull->getType()); | 
|  | 3021 | return Builder.CreateSelect(IsNotNull, Src, DstNull); | 
|  | 3022 | } | 
|  | 3023 |  | 
|  | 3024 | llvm::BasicBlock *OriginalBB = Builder.GetInsertBlock(); | 
|  | 3025 | llvm::BasicBlock *ConvertBB = CGF.createBasicBlock("memptr.convert"); | 
|  | 3026 | llvm::BasicBlock *ContinueBB = CGF.createBasicBlock("memptr.converted"); | 
|  | 3027 | Builder.CreateCondBr(IsNotNull, ConvertBB, ContinueBB); | 
|  | 3028 | CGF.EmitBlock(ConvertBB); | 
|  | 3029 |  | 
| David Majnemer | 0d9ad68 | 2015-06-29 00:06:50 +0000 | [diff] [blame] | 3030 | llvm::Value *Dst = EmitNonNullMemberPointerConversion( | 
|  | 3031 | SrcTy, DstTy, E->getCastKind(), E->path_begin(), E->path_end(), Src, | 
|  | 3032 | Builder); | 
|  | 3033 |  | 
|  | 3034 | Builder.CreateBr(ContinueBB); | 
|  | 3035 |  | 
|  | 3036 | // In the continuation, choose between DstNull and Dst. | 
|  | 3037 | CGF.EmitBlock(ContinueBB); | 
|  | 3038 | llvm::PHINode *Phi = Builder.CreatePHI(DstNull->getType(), 2, "memptr.converted"); | 
|  | 3039 | Phi->addIncoming(DstNull, OriginalBB); | 
|  | 3040 | Phi->addIncoming(Dst, ConvertBB); | 
|  | 3041 | return Phi; | 
|  | 3042 | } | 
|  | 3043 |  | 
|  | 3044 | llvm::Value *MicrosoftCXXABI::EmitNonNullMemberPointerConversion( | 
|  | 3045 | const MemberPointerType *SrcTy, const MemberPointerType *DstTy, CastKind CK, | 
|  | 3046 | CastExpr::path_const_iterator PathBegin, | 
|  | 3047 | CastExpr::path_const_iterator PathEnd, llvm::Value *Src, | 
|  | 3048 | CGBuilderTy &Builder) { | 
|  | 3049 | const CXXRecordDecl *SrcRD = SrcTy->getMostRecentCXXRecordDecl(); | 
|  | 3050 | const CXXRecordDecl *DstRD = DstTy->getMostRecentCXXRecordDecl(); | 
|  | 3051 | MSInheritanceAttr::Spelling SrcInheritance = SrcRD->getMSInheritanceModel(); | 
|  | 3052 | MSInheritanceAttr::Spelling DstInheritance = DstRD->getMSInheritanceModel(); | 
|  | 3053 | bool IsFunc = SrcTy->isMemberFunctionPointer(); | 
|  | 3054 | bool IsConstant = isa<llvm::Constant>(Src); | 
|  | 3055 |  | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 3056 | // Decompose src. | 
|  | 3057 | llvm::Value *FirstField = Src; | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 3058 | llvm::Value *NonVirtualBaseAdjustment = getZeroInt(); | 
|  | 3059 | llvm::Value *VirtualBaseAdjustmentOffset = getZeroInt(); | 
|  | 3060 | llvm::Value *VBPtrOffset = getZeroInt(); | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 3061 | if (!MSInheritanceAttr::hasOnlyOneField(IsFunc, SrcInheritance)) { | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 3062 | // We need to extract values. | 
|  | 3063 | unsigned I = 0; | 
|  | 3064 | FirstField = Builder.CreateExtractValue(Src, I++); | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 3065 | if (MSInheritanceAttr::hasNVOffsetField(IsFunc, SrcInheritance)) | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 3066 | NonVirtualBaseAdjustment = Builder.CreateExtractValue(Src, I++); | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 3067 | if (MSInheritanceAttr::hasVBPtrOffsetField(SrcInheritance)) | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 3068 | VBPtrOffset = Builder.CreateExtractValue(Src, I++); | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 3069 | if (MSInheritanceAttr::hasVBTableOffsetField(SrcInheritance)) | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 3070 | VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(Src, I++); | 
|  | 3071 | } | 
|  | 3072 |  | 
| David Majnemer | 0d9ad68 | 2015-06-29 00:06:50 +0000 | [diff] [blame] | 3073 | bool IsDerivedToBase = (CK == CK_DerivedToBaseMemberPointer); | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 3074 | const MemberPointerType *DerivedTy = IsDerivedToBase ? SrcTy : DstTy; | 
|  | 3075 | const CXXRecordDecl *DerivedClass = DerivedTy->getMostRecentCXXRecordDecl(); | 
|  | 3076 |  | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 3077 | // For data pointers, we adjust the field offset directly.  For functions, we | 
|  | 3078 | // have a separate field. | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 3079 | llvm::Value *&NVAdjustField = IsFunc ? NonVirtualBaseAdjustment : FirstField; | 
|  | 3080 |  | 
|  | 3081 | // The virtual inheritance model has a quirk: the virtual base table is always | 
|  | 3082 | // referenced when dereferencing a member pointer even if the member pointer | 
|  | 3083 | // is non-virtual.  This is accounted for by adjusting the non-virtual offset | 
|  | 3084 | // to point backwards to the top of the MDC from the first VBase.  Undo this | 
|  | 3085 | // adjustment to normalize the member pointer. | 
|  | 3086 | llvm::Value *SrcVBIndexEqZero = | 
|  | 3087 | Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt()); | 
|  | 3088 | if (SrcInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) { | 
|  | 3089 | if (int64_t SrcOffsetToFirstVBase = | 
| David Majnemer | 08ef2ba | 2015-06-23 20:34:18 +0000 | [diff] [blame] | 3090 | getContext().getOffsetOfBaseWithVBPtr(SrcRD).getQuantity()) { | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 3091 | llvm::Value *UndoSrcAdjustment = Builder.CreateSelect( | 
|  | 3092 | SrcVBIndexEqZero, | 
|  | 3093 | llvm::ConstantInt::get(CGM.IntTy, SrcOffsetToFirstVBase), | 
|  | 3094 | getZeroInt()); | 
|  | 3095 | NVAdjustField = Builder.CreateNSWAdd(NVAdjustField, UndoSrcAdjustment); | 
|  | 3096 | } | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 3097 | } | 
|  | 3098 |  | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 3099 | // A non-zero vbindex implies that we are dealing with a source member in a | 
|  | 3100 | // floating virtual base in addition to some non-virtual offset.  If the | 
|  | 3101 | // vbindex is zero, we are dealing with a source that exists in a non-virtual, | 
|  | 3102 | // fixed, base.  The difference between these two cases is that the vbindex + | 
|  | 3103 | // nvoffset *always* point to the member regardless of what context they are | 
|  | 3104 | // evaluated in so long as the vbindex is adjusted.  A member inside a fixed | 
|  | 3105 | // base requires explicit nv adjustment. | 
|  | 3106 | llvm::Constant *BaseClassOffset = llvm::ConstantInt::get( | 
| David Majnemer | 0d9ad68 | 2015-06-29 00:06:50 +0000 | [diff] [blame] | 3107 | CGM.IntTy, | 
|  | 3108 | CGM.computeNonVirtualBaseClassOffset(DerivedClass, PathBegin, PathEnd) | 
|  | 3109 | .getQuantity()); | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 3110 |  | 
|  | 3111 | llvm::Value *NVDisp; | 
|  | 3112 | if (IsDerivedToBase) | 
|  | 3113 | NVDisp = Builder.CreateNSWSub(NVAdjustField, BaseClassOffset, "adj"); | 
|  | 3114 | else | 
|  | 3115 | NVDisp = Builder.CreateNSWAdd(NVAdjustField, BaseClassOffset, "adj"); | 
|  | 3116 |  | 
|  | 3117 | NVAdjustField = Builder.CreateSelect(SrcVBIndexEqZero, NVDisp, getZeroInt()); | 
|  | 3118 |  | 
|  | 3119 | // Update the vbindex to an appropriate value in the destination because | 
|  | 3120 | // SrcRD's vbtable might not be a strict prefix of the one in DstRD. | 
|  | 3121 | llvm::Value *DstVBIndexEqZero = SrcVBIndexEqZero; | 
|  | 3122 | if (MSInheritanceAttr::hasVBTableOffsetField(DstInheritance) && | 
|  | 3123 | MSInheritanceAttr::hasVBTableOffsetField(SrcInheritance)) { | 
|  | 3124 | if (llvm::GlobalVariable *VDispMap = | 
|  | 3125 | getAddrOfVirtualDisplacementMap(SrcRD, DstRD)) { | 
|  | 3126 | llvm::Value *VBIndex = Builder.CreateExactUDiv( | 
|  | 3127 | VirtualBaseAdjustmentOffset, llvm::ConstantInt::get(CGM.IntTy, 4)); | 
| David Majnemer | 0d9ad68 | 2015-06-29 00:06:50 +0000 | [diff] [blame] | 3128 | if (IsConstant) { | 
|  | 3129 | llvm::Constant *Mapping = VDispMap->getInitializer(); | 
|  | 3130 | VirtualBaseAdjustmentOffset = | 
|  | 3131 | Mapping->getAggregateElement(cast<llvm::Constant>(VBIndex)); | 
|  | 3132 | } else { | 
|  | 3133 | llvm::Value *Idxs[] = {getZeroInt(), VBIndex}; | 
|  | 3134 | VirtualBaseAdjustmentOffset = | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 3135 | Builder.CreateAlignedLoad(Builder.CreateInBoundsGEP(VDispMap, Idxs), | 
|  | 3136 | CharUnits::fromQuantity(4)); | 
| David Majnemer | 0d9ad68 | 2015-06-29 00:06:50 +0000 | [diff] [blame] | 3137 | } | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 3138 |  | 
|  | 3139 | DstVBIndexEqZero = | 
|  | 3140 | Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt()); | 
|  | 3141 | } | 
|  | 3142 | } | 
|  | 3143 |  | 
|  | 3144 | // Set the VBPtrOffset to zero if the vbindex is zero.  Otherwise, initialize | 
|  | 3145 | // it to the offset of the vbptr. | 
|  | 3146 | if (MSInheritanceAttr::hasVBPtrOffsetField(DstInheritance)) { | 
|  | 3147 | llvm::Value *DstVBPtrOffset = llvm::ConstantInt::get( | 
|  | 3148 | CGM.IntTy, | 
|  | 3149 | getContext().getASTRecordLayout(DstRD).getVBPtrOffset().getQuantity()); | 
|  | 3150 | VBPtrOffset = | 
|  | 3151 | Builder.CreateSelect(DstVBIndexEqZero, getZeroInt(), DstVBPtrOffset); | 
|  | 3152 | } | 
|  | 3153 |  | 
|  | 3154 | // Likewise, apply a similar adjustment so that dereferencing the member | 
|  | 3155 | // pointer correctly accounts for the distance between the start of the first | 
|  | 3156 | // virtual base and the top of the MDC. | 
|  | 3157 | if (DstInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) { | 
|  | 3158 | if (int64_t DstOffsetToFirstVBase = | 
| David Majnemer | 08ef2ba | 2015-06-23 20:34:18 +0000 | [diff] [blame] | 3159 | getContext().getOffsetOfBaseWithVBPtr(DstRD).getQuantity()) { | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 3160 | llvm::Value *DoDstAdjustment = Builder.CreateSelect( | 
|  | 3161 | DstVBIndexEqZero, | 
|  | 3162 | llvm::ConstantInt::get(CGM.IntTy, DstOffsetToFirstVBase), | 
|  | 3163 | getZeroInt()); | 
|  | 3164 | NVAdjustField = Builder.CreateNSWSub(NVAdjustField, DoDstAdjustment); | 
|  | 3165 | } | 
|  | 3166 | } | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 3167 |  | 
|  | 3168 | // Recompose dst from the null struct and the adjusted fields from src. | 
|  | 3169 | llvm::Value *Dst; | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 3170 | if (MSInheritanceAttr::hasOnlyOneField(IsFunc, DstInheritance)) { | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 3171 | Dst = FirstField; | 
|  | 3172 | } else { | 
| David Majnemer | 0d9ad68 | 2015-06-29 00:06:50 +0000 | [diff] [blame] | 3173 | Dst = llvm::UndefValue::get(ConvertMemberPointerType(DstTy)); | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 3174 | unsigned Idx = 0; | 
|  | 3175 | Dst = Builder.CreateInsertValue(Dst, FirstField, Idx++); | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 3176 | if (MSInheritanceAttr::hasNVOffsetField(IsFunc, DstInheritance)) | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 3177 | Dst = Builder.CreateInsertValue(Dst, NonVirtualBaseAdjustment, Idx++); | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 3178 | if (MSInheritanceAttr::hasVBPtrOffsetField(DstInheritance)) | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 3179 | Dst = Builder.CreateInsertValue(Dst, VBPtrOffset, Idx++); | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 3180 | if (MSInheritanceAttr::hasVBTableOffsetField(DstInheritance)) | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 3181 | Dst = Builder.CreateInsertValue(Dst, VirtualBaseAdjustmentOffset, Idx++); | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 3182 | } | 
| David Majnemer | 0d9ad68 | 2015-06-29 00:06:50 +0000 | [diff] [blame] | 3183 | return Dst; | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 3184 | } | 
|  | 3185 |  | 
|  | 3186 | llvm::Constant * | 
|  | 3187 | MicrosoftCXXABI::EmitMemberPointerConversion(const CastExpr *E, | 
|  | 3188 | llvm::Constant *Src) { | 
|  | 3189 | const MemberPointerType *SrcTy = | 
| David Majnemer | 5ca193c | 2015-06-23 07:31:07 +0000 | [diff] [blame] | 3190 | E->getSubExpr()->getType()->castAs<MemberPointerType>(); | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 3191 | const MemberPointerType *DstTy = E->getType()->castAs<MemberPointerType>(); | 
|  | 3192 |  | 
| David Majnemer | 5ca193c | 2015-06-23 07:31:07 +0000 | [diff] [blame] | 3193 | CastKind CK = E->getCastKind(); | 
|  | 3194 |  | 
|  | 3195 | return EmitMemberPointerConversion(SrcTy, DstTy, CK, E->path_begin(), | 
|  | 3196 | E->path_end(), Src); | 
|  | 3197 | } | 
|  | 3198 |  | 
|  | 3199 | llvm::Constant *MicrosoftCXXABI::EmitMemberPointerConversion( | 
|  | 3200 | const MemberPointerType *SrcTy, const MemberPointerType *DstTy, CastKind CK, | 
|  | 3201 | CastExpr::path_const_iterator PathBegin, | 
|  | 3202 | CastExpr::path_const_iterator PathEnd, llvm::Constant *Src) { | 
|  | 3203 | assert(CK == CK_DerivedToBaseMemberPointer || | 
|  | 3204 | CK == CK_BaseToDerivedMemberPointer || | 
|  | 3205 | CK == CK_ReinterpretMemberPointer); | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 3206 | // If src is null, emit a new null for dst.  We can't return src because dst | 
|  | 3207 | // might have a new representation. | 
|  | 3208 | if (MemberPointerConstantIsNull(SrcTy, Src)) | 
|  | 3209 | return EmitNullMemberPointer(DstTy); | 
|  | 3210 |  | 
|  | 3211 | // We don't need to do anything for reinterpret_casts of non-null member | 
|  | 3212 | // pointers.  We should only get here when the two type representations have | 
|  | 3213 | // the same size. | 
| David Majnemer | 5ca193c | 2015-06-23 07:31:07 +0000 | [diff] [blame] | 3214 | if (CK == CK_ReinterpretMemberPointer) | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 3215 | return Src; | 
|  | 3216 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 3217 | CGBuilderTy Builder(CGM, CGM.getLLVMContext()); | 
| David Majnemer | 0d9ad68 | 2015-06-29 00:06:50 +0000 | [diff] [blame] | 3218 | auto *Dst = cast<llvm::Constant>(EmitNonNullMemberPointerConversion( | 
|  | 3219 | SrcTy, DstTy, CK, PathBegin, PathEnd, Src, Builder)); | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 3220 |  | 
| David Majnemer | 0d9ad68 | 2015-06-29 00:06:50 +0000 | [diff] [blame] | 3221 | return Dst; | 
| Reid Kleckner | 452abac | 2013-05-09 21:01:17 +0000 | [diff] [blame] | 3222 | } | 
|  | 3223 |  | 
| David Majnemer | 2b0d66d | 2014-02-20 23:22:07 +0000 | [diff] [blame] | 3224 | llvm::Value *MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer( | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 3225 | CodeGenFunction &CGF, const Expr *E, Address This, | 
|  | 3226 | llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr, | 
|  | 3227 | const MemberPointerType *MPT) { | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 3228 | assert(MPT->isMemberFunctionPointer()); | 
|  | 3229 | const FunctionProtoType *FPT = | 
|  | 3230 | MPT->getPointeeType()->castAs<FunctionProtoType>(); | 
| David Majnemer | 1cdd96d | 2014-01-17 09:01:00 +0000 | [diff] [blame] | 3231 | const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); | 
| George Burgess IV | 3e3bb95b | 2015-12-02 21:58:08 +0000 | [diff] [blame] | 3232 | llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType( | 
|  | 3233 | CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr)); | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 3234 | CGBuilderTy &Builder = CGF.Builder; | 
|  | 3235 |  | 
| David Majnemer | 1cdd96d | 2014-01-17 09:01:00 +0000 | [diff] [blame] | 3236 | MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 3237 |  | 
|  | 3238 | // Extract the fields we need, regardless of model.  We'll apply them if we | 
|  | 3239 | // have them. | 
|  | 3240 | llvm::Value *FunctionPointer = MemPtr; | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 3241 | llvm::Value *NonVirtualBaseAdjustment = nullptr; | 
|  | 3242 | llvm::Value *VirtualBaseAdjustmentOffset = nullptr; | 
|  | 3243 | llvm::Value *VBPtrOffset = nullptr; | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 3244 | if (MemPtr->getType()->isStructTy()) { | 
|  | 3245 | // We need to extract values. | 
|  | 3246 | unsigned I = 0; | 
|  | 3247 | FunctionPointer = Builder.CreateExtractValue(MemPtr, I++); | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 3248 | if (MSInheritanceAttr::hasNVOffsetField(MPT, Inheritance)) | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 3249 | NonVirtualBaseAdjustment = Builder.CreateExtractValue(MemPtr, I++); | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 3250 | if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) | 
| Reid Kleckner | 7d0efb5 | 2013-05-03 01:15:11 +0000 | [diff] [blame] | 3251 | VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++); | 
| Reid Kleckner | 96f8f93 | 2014-02-05 17:27:08 +0000 | [diff] [blame] | 3252 | if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance)) | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 3253 | VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++); | 
|  | 3254 | } | 
|  | 3255 |  | 
|  | 3256 | if (VirtualBaseAdjustmentOffset) { | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 3257 | ThisPtrForCall = AdjustVirtualBase(CGF, E, RD, This, | 
|  | 3258 | VirtualBaseAdjustmentOffset, VBPtrOffset); | 
|  | 3259 | } else { | 
|  | 3260 | ThisPtrForCall = This.getPointer(); | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 3261 | } | 
|  | 3262 |  | 
|  | 3263 | if (NonVirtualBaseAdjustment) { | 
|  | 3264 | // Apply the adjustment and cast back to the original struct type. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 3265 | llvm::Value *Ptr = Builder.CreateBitCast(ThisPtrForCall, CGF.Int8PtrTy); | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 3266 | Ptr = Builder.CreateInBoundsGEP(Ptr, NonVirtualBaseAdjustment); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 3267 | ThisPtrForCall = Builder.CreateBitCast(Ptr, ThisPtrForCall->getType(), | 
|  | 3268 | "this.adjusted"); | 
| Reid Kleckner | 2341ae3 | 2013-04-11 18:13:19 +0000 | [diff] [blame] | 3269 | } | 
|  | 3270 |  | 
|  | 3271 | return Builder.CreateBitCast(FunctionPointer, FTy->getPointerTo()); | 
|  | 3272 | } | 
|  | 3273 |  | 
| Charles Davis | 53c59df | 2010-08-16 03:33:14 +0000 | [diff] [blame] | 3274 | CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) { | 
| Charles Davis | 74ce859 | 2010-06-09 23:25:41 +0000 | [diff] [blame] | 3275 | return new MicrosoftCXXABI(CGM); | 
|  | 3276 | } | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3277 |  | 
|  | 3278 | // MS RTTI Overview: | 
|  | 3279 | // The run time type information emitted by cl.exe contains 5 distinct types of | 
|  | 3280 | // structures.  Many of them reference each other. | 
|  | 3281 | // | 
|  | 3282 | // TypeInfo:  Static classes that are returned by typeid. | 
|  | 3283 | // | 
|  | 3284 | // CompleteObjectLocator:  Referenced by vftables.  They contain information | 
|  | 3285 | //   required for dynamic casting, including OffsetFromTop.  They also contain | 
|  | 3286 | //   a reference to the TypeInfo for the type and a reference to the | 
|  | 3287 | //   CompleteHierarchyDescriptor for the type. | 
|  | 3288 | // | 
|  | 3289 | // ClassHieararchyDescriptor: Contains information about a class hierarchy. | 
|  | 3290 | //   Used during dynamic_cast to walk a class hierarchy.  References a base | 
|  | 3291 | //   class array and the size of said array. | 
|  | 3292 | // | 
|  | 3293 | // BaseClassArray: Contains a list of classes in a hierarchy.  BaseClassArray is | 
|  | 3294 | //   somewhat of a misnomer because the most derived class is also in the list | 
|  | 3295 | //   as well as multiple copies of virtual bases (if they occur multiple times | 
|  | 3296 | //   in the hiearchy.)  The BaseClassArray contains one BaseClassDescriptor for | 
|  | 3297 | //   every path in the hierarchy, in pre-order depth first order.  Note, we do | 
|  | 3298 | //   not declare a specific llvm type for BaseClassArray, it's merely an array | 
|  | 3299 | //   of BaseClassDescriptor pointers. | 
|  | 3300 | // | 
|  | 3301 | // BaseClassDescriptor: Contains information about a class in a class hierarchy. | 
|  | 3302 | //   BaseClassDescriptor is also somewhat of a misnomer for the same reason that | 
|  | 3303 | //   BaseClassArray is.  It contains information about a class within a | 
|  | 3304 | //   hierarchy such as: is this base is ambiguous and what is its offset in the | 
|  | 3305 | //   vbtable.  The names of the BaseClassDescriptors have all of their fields | 
|  | 3306 | //   mangled into them so they can be aggressively deduplicated by the linker. | 
|  | 3307 |  | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3308 | static llvm::GlobalVariable *getTypeInfoVTable(CodeGenModule &CGM) { | 
|  | 3309 | StringRef MangledName("\01??_7type_info@@6B@"); | 
|  | 3310 | if (auto VTable = CGM.getModule().getNamedGlobal(MangledName)) | 
|  | 3311 | return VTable; | 
|  | 3312 | return new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy, | 
|  | 3313 | /*Constant=*/true, | 
|  | 3314 | llvm::GlobalVariable::ExternalLinkage, | 
|  | 3315 | /*Initializer=*/nullptr, MangledName); | 
|  | 3316 | } | 
|  | 3317 |  | 
|  | 3318 | namespace { | 
|  | 3319 |  | 
|  | 3320 | /// \brief A Helper struct that stores information about a class in a class | 
|  | 3321 | /// hierarchy.  The information stored in these structs struct is used during | 
|  | 3322 | /// the generation of ClassHierarchyDescriptors and BaseClassDescriptors. | 
|  | 3323 | // During RTTI creation, MSRTTIClasses are stored in a contiguous array with | 
|  | 3324 | // implicit depth first pre-order tree connectivity.  getFirstChild and | 
|  | 3325 | // getNextSibling allow us to walk the tree efficiently. | 
|  | 3326 | struct MSRTTIClass { | 
|  | 3327 | enum { | 
|  | 3328 | IsPrivateOnPath = 1 | 8, | 
|  | 3329 | IsAmbiguous = 2, | 
|  | 3330 | IsPrivate = 4, | 
|  | 3331 | IsVirtual = 16, | 
|  | 3332 | HasHierarchyDescriptor = 64 | 
|  | 3333 | }; | 
|  | 3334 | MSRTTIClass(const CXXRecordDecl *RD) : RD(RD) {} | 
|  | 3335 | uint32_t initialize(const MSRTTIClass *Parent, | 
|  | 3336 | const CXXBaseSpecifier *Specifier); | 
|  | 3337 |  | 
|  | 3338 | MSRTTIClass *getFirstChild() { return this + 1; } | 
|  | 3339 | static MSRTTIClass *getNextChild(MSRTTIClass *Child) { | 
|  | 3340 | return Child + 1 + Child->NumBases; | 
|  | 3341 | } | 
|  | 3342 |  | 
|  | 3343 | const CXXRecordDecl *RD, *VirtualRoot; | 
|  | 3344 | uint32_t Flags, NumBases, OffsetInVBase; | 
|  | 3345 | }; | 
|  | 3346 |  | 
|  | 3347 | /// \brief Recursively initialize the base class array. | 
|  | 3348 | uint32_t MSRTTIClass::initialize(const MSRTTIClass *Parent, | 
|  | 3349 | const CXXBaseSpecifier *Specifier) { | 
|  | 3350 | Flags = HasHierarchyDescriptor; | 
|  | 3351 | if (!Parent) { | 
|  | 3352 | VirtualRoot = nullptr; | 
|  | 3353 | OffsetInVBase = 0; | 
|  | 3354 | } else { | 
|  | 3355 | if (Specifier->getAccessSpecifier() != AS_public) | 
|  | 3356 | Flags |= IsPrivate | IsPrivateOnPath; | 
|  | 3357 | if (Specifier->isVirtual()) { | 
|  | 3358 | Flags |= IsVirtual; | 
|  | 3359 | VirtualRoot = RD; | 
|  | 3360 | OffsetInVBase = 0; | 
|  | 3361 | } else { | 
|  | 3362 | if (Parent->Flags & IsPrivateOnPath) | 
|  | 3363 | Flags |= IsPrivateOnPath; | 
|  | 3364 | VirtualRoot = Parent->VirtualRoot; | 
|  | 3365 | OffsetInVBase = Parent->OffsetInVBase + RD->getASTContext() | 
|  | 3366 | .getASTRecordLayout(Parent->RD).getBaseClassOffset(RD).getQuantity(); | 
|  | 3367 | } | 
|  | 3368 | } | 
|  | 3369 | NumBases = 0; | 
|  | 3370 | MSRTTIClass *Child = getFirstChild(); | 
|  | 3371 | for (const CXXBaseSpecifier &Base : RD->bases()) { | 
|  | 3372 | NumBases += Child->initialize(this, &Base) + 1; | 
|  | 3373 | Child = getNextChild(Child); | 
|  | 3374 | } | 
|  | 3375 | return NumBases; | 
|  | 3376 | } | 
|  | 3377 |  | 
|  | 3378 | static llvm::GlobalValue::LinkageTypes getLinkageForRTTI(QualType Ty) { | 
|  | 3379 | switch (Ty->getLinkage()) { | 
|  | 3380 | case NoLinkage: | 
|  | 3381 | case InternalLinkage: | 
|  | 3382 | case UniqueExternalLinkage: | 
|  | 3383 | return llvm::GlobalValue::InternalLinkage; | 
|  | 3384 |  | 
|  | 3385 | case VisibleNoLinkage: | 
|  | 3386 | case ExternalLinkage: | 
|  | 3387 | return llvm::GlobalValue::LinkOnceODRLinkage; | 
|  | 3388 | } | 
|  | 3389 | llvm_unreachable("Invalid linkage!"); | 
|  | 3390 | } | 
|  | 3391 |  | 
|  | 3392 | /// \brief An ephemeral helper class for building MS RTTI types.  It caches some | 
|  | 3393 | /// calls to the module and information about the most derived class in a | 
|  | 3394 | /// hierarchy. | 
|  | 3395 | struct MSRTTIBuilder { | 
|  | 3396 | enum { | 
|  | 3397 | HasBranchingHierarchy = 1, | 
|  | 3398 | HasVirtualBranchingHierarchy = 2, | 
|  | 3399 | HasAmbiguousBases = 4 | 
|  | 3400 | }; | 
|  | 3401 |  | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3402 | MSRTTIBuilder(MicrosoftCXXABI &ABI, const CXXRecordDecl *RD) | 
|  | 3403 | : CGM(ABI.CGM), Context(CGM.getContext()), | 
|  | 3404 | VMContext(CGM.getLLVMContext()), Module(CGM.getModule()), RD(RD), | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3405 | Linkage(getLinkageForRTTI(CGM.getContext().getTagDeclType(RD))), | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3406 | ABI(ABI) {} | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3407 |  | 
|  | 3408 | llvm::GlobalVariable *getBaseClassDescriptor(const MSRTTIClass &Classes); | 
|  | 3409 | llvm::GlobalVariable * | 
|  | 3410 | getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes); | 
|  | 3411 | llvm::GlobalVariable *getClassHierarchyDescriptor(); | 
|  | 3412 | llvm::GlobalVariable *getCompleteObjectLocator(const VPtrInfo *Info); | 
|  | 3413 |  | 
|  | 3414 | CodeGenModule &CGM; | 
|  | 3415 | ASTContext &Context; | 
|  | 3416 | llvm::LLVMContext &VMContext; | 
|  | 3417 | llvm::Module &Module; | 
|  | 3418 | const CXXRecordDecl *RD; | 
|  | 3419 | llvm::GlobalVariable::LinkageTypes Linkage; | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3420 | MicrosoftCXXABI &ABI; | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3421 | }; | 
|  | 3422 |  | 
|  | 3423 | } // namespace | 
|  | 3424 |  | 
|  | 3425 | /// \brief Recursively serializes a class hierarchy in pre-order depth first | 
|  | 3426 | /// order. | 
|  | 3427 | static void serializeClassHierarchy(SmallVectorImpl<MSRTTIClass> &Classes, | 
|  | 3428 | const CXXRecordDecl *RD) { | 
|  | 3429 | Classes.push_back(MSRTTIClass(RD)); | 
|  | 3430 | for (const CXXBaseSpecifier &Base : RD->bases()) | 
|  | 3431 | serializeClassHierarchy(Classes, Base.getType()->getAsCXXRecordDecl()); | 
|  | 3432 | } | 
|  | 3433 |  | 
|  | 3434 | /// \brief Find ambiguity among base classes. | 
|  | 3435 | static void | 
|  | 3436 | detectAmbiguousBases(SmallVectorImpl<MSRTTIClass> &Classes) { | 
|  | 3437 | llvm::SmallPtrSet<const CXXRecordDecl *, 8> VirtualBases; | 
|  | 3438 | llvm::SmallPtrSet<const CXXRecordDecl *, 8> UniqueBases; | 
|  | 3439 | llvm::SmallPtrSet<const CXXRecordDecl *, 8> AmbiguousBases; | 
|  | 3440 | for (MSRTTIClass *Class = &Classes.front(); Class <= &Classes.back();) { | 
|  | 3441 | if ((Class->Flags & MSRTTIClass::IsVirtual) && | 
| David Blaikie | 82e95a3 | 2014-11-19 07:49:47 +0000 | [diff] [blame] | 3442 | !VirtualBases.insert(Class->RD).second) { | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3443 | Class = MSRTTIClass::getNextChild(Class); | 
|  | 3444 | continue; | 
|  | 3445 | } | 
| David Blaikie | 82e95a3 | 2014-11-19 07:49:47 +0000 | [diff] [blame] | 3446 | if (!UniqueBases.insert(Class->RD).second) | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3447 | AmbiguousBases.insert(Class->RD); | 
|  | 3448 | Class++; | 
|  | 3449 | } | 
|  | 3450 | if (AmbiguousBases.empty()) | 
|  | 3451 | return; | 
|  | 3452 | for (MSRTTIClass &Class : Classes) | 
|  | 3453 | if (AmbiguousBases.count(Class.RD)) | 
|  | 3454 | Class.Flags |= MSRTTIClass::IsAmbiguous; | 
|  | 3455 | } | 
|  | 3456 |  | 
|  | 3457 | llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() { | 
|  | 3458 | SmallString<256> MangledName; | 
|  | 3459 | { | 
|  | 3460 | llvm::raw_svector_ostream Out(MangledName); | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3461 | ABI.getMangleContext().mangleCXXRTTIClassHierarchyDescriptor(RD, Out); | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3462 | } | 
|  | 3463 |  | 
|  | 3464 | // Check to see if we've already declared this ClassHierarchyDescriptor. | 
|  | 3465 | if (auto CHD = Module.getNamedGlobal(MangledName)) | 
|  | 3466 | return CHD; | 
|  | 3467 |  | 
|  | 3468 | // Serialize the class hierarchy and initialize the CHD Fields. | 
|  | 3469 | SmallVector<MSRTTIClass, 8> Classes; | 
|  | 3470 | serializeClassHierarchy(Classes, RD); | 
|  | 3471 | Classes.front().initialize(/*Parent=*/nullptr, /*Specifier=*/nullptr); | 
|  | 3472 | detectAmbiguousBases(Classes); | 
|  | 3473 | int Flags = 0; | 
|  | 3474 | for (auto Class : Classes) { | 
|  | 3475 | if (Class.RD->getNumBases() > 1) | 
|  | 3476 | Flags |= HasBranchingHierarchy; | 
|  | 3477 | // Note: cl.exe does not calculate "HasAmbiguousBases" correctly.  We | 
|  | 3478 | // believe the field isn't actually used. | 
|  | 3479 | if (Class.Flags & MSRTTIClass::IsAmbiguous) | 
|  | 3480 | Flags |= HasAmbiguousBases; | 
|  | 3481 | } | 
|  | 3482 | if ((Flags & HasBranchingHierarchy) && RD->getNumVBases() != 0) | 
|  | 3483 | Flags |= HasVirtualBranchingHierarchy; | 
|  | 3484 | // These gep indices are used to get the address of the first element of the | 
|  | 3485 | // base class array. | 
|  | 3486 | llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.IntTy, 0), | 
|  | 3487 | llvm::ConstantInt::get(CGM.IntTy, 0)}; | 
|  | 3488 |  | 
|  | 3489 | // Forward-declare the class hierarchy descriptor | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3490 | auto Type = ABI.getClassHierarchyDescriptorType(); | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3491 | auto CHD = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage, | 
|  | 3492 | /*Initializer=*/nullptr, | 
| Yaron Keren | 2c07cc7 | 2015-12-01 08:14:39 +0000 | [diff] [blame] | 3493 | MangledName); | 
| Rafael Espindola | 654542a | 2015-01-16 19:23:42 +0000 | [diff] [blame] | 3494 | if (CHD->isWeakForLinker()) | 
|  | 3495 | CHD->setComdat(CGM.getModule().getOrInsertComdat(CHD->getName())); | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3496 |  | 
| David Blaikie | e3b172a | 2015-04-02 18:55:21 +0000 | [diff] [blame] | 3497 | auto *Bases = getBaseClassArray(Classes); | 
|  | 3498 |  | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3499 | // Initialize the base class ClassHierarchyDescriptor. | 
|  | 3500 | llvm::Constant *Fields[] = { | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3501 | llvm::ConstantInt::get(CGM.IntTy, 0), // Unknown | 
|  | 3502 | llvm::ConstantInt::get(CGM.IntTy, Flags), | 
|  | 3503 | llvm::ConstantInt::get(CGM.IntTy, Classes.size()), | 
|  | 3504 | ABI.getImageRelativeConstant(llvm::ConstantExpr::getInBoundsGetElementPtr( | 
| David Blaikie | e3b172a | 2015-04-02 18:55:21 +0000 | [diff] [blame] | 3505 | Bases->getValueType(), Bases, | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3506 | llvm::ArrayRef<llvm::Value *>(GEPIndices))), | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3507 | }; | 
|  | 3508 | CHD->setInitializer(llvm::ConstantStruct::get(Type, Fields)); | 
|  | 3509 | return CHD; | 
|  | 3510 | } | 
|  | 3511 |  | 
|  | 3512 | llvm::GlobalVariable * | 
|  | 3513 | MSRTTIBuilder::getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes) { | 
|  | 3514 | SmallString<256> MangledName; | 
|  | 3515 | { | 
|  | 3516 | llvm::raw_svector_ostream Out(MangledName); | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3517 | ABI.getMangleContext().mangleCXXRTTIBaseClassArray(RD, Out); | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3518 | } | 
|  | 3519 |  | 
|  | 3520 | // Forward-declare the base class array. | 
|  | 3521 | // cl.exe pads the base class array with 1 (in 32 bit mode) or 4 (in 64 bit | 
|  | 3522 | // mode) bytes of padding.  We provide a pointer sized amount of padding by | 
|  | 3523 | // adding +1 to Classes.size().  The sections have pointer alignment and are | 
|  | 3524 | // marked pick-any so it shouldn't matter. | 
| David Majnemer | 26a90f8 | 2014-07-07 15:29:10 +0000 | [diff] [blame] | 3525 | llvm::Type *PtrType = ABI.getImageRelativeType( | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3526 | ABI.getBaseClassDescriptorType()->getPointerTo()); | 
| David Majnemer | 26a90f8 | 2014-07-07 15:29:10 +0000 | [diff] [blame] | 3527 | auto *ArrType = llvm::ArrayType::get(PtrType, Classes.size() + 1); | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 3528 | auto *BCA = | 
|  | 3529 | new llvm::GlobalVariable(Module, ArrType, | 
|  | 3530 | /*Constant=*/true, Linkage, | 
| Yaron Keren | 2c07cc7 | 2015-12-01 08:14:39 +0000 | [diff] [blame] | 3531 | /*Initializer=*/nullptr, MangledName); | 
| Rafael Espindola | 654542a | 2015-01-16 19:23:42 +0000 | [diff] [blame] | 3532 | if (BCA->isWeakForLinker()) | 
|  | 3533 | BCA->setComdat(CGM.getModule().getOrInsertComdat(BCA->getName())); | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3534 |  | 
|  | 3535 | // Initialize the BaseClassArray. | 
|  | 3536 | SmallVector<llvm::Constant *, 8> BaseClassArrayData; | 
|  | 3537 | for (MSRTTIClass &Class : Classes) | 
|  | 3538 | BaseClassArrayData.push_back( | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3539 | ABI.getImageRelativeConstant(getBaseClassDescriptor(Class))); | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3540 | BaseClassArrayData.push_back(llvm::Constant::getNullValue(PtrType)); | 
| David Majnemer | 26a90f8 | 2014-07-07 15:29:10 +0000 | [diff] [blame] | 3541 | BCA->setInitializer(llvm::ConstantArray::get(ArrType, BaseClassArrayData)); | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3542 | return BCA; | 
|  | 3543 | } | 
|  | 3544 |  | 
|  | 3545 | llvm::GlobalVariable * | 
|  | 3546 | MSRTTIBuilder::getBaseClassDescriptor(const MSRTTIClass &Class) { | 
|  | 3547 | // Compute the fields for the BaseClassDescriptor.  They are computed up front | 
|  | 3548 | // because they are mangled into the name of the object. | 
|  | 3549 | uint32_t OffsetInVBTable = 0; | 
|  | 3550 | int32_t VBPtrOffset = -1; | 
|  | 3551 | if (Class.VirtualRoot) { | 
|  | 3552 | auto &VTableContext = CGM.getMicrosoftVTableContext(); | 
|  | 3553 | OffsetInVBTable = VTableContext.getVBTableIndex(RD, Class.VirtualRoot) * 4; | 
|  | 3554 | VBPtrOffset = Context.getASTRecordLayout(RD).getVBPtrOffset().getQuantity(); | 
|  | 3555 | } | 
|  | 3556 |  | 
|  | 3557 | SmallString<256> MangledName; | 
|  | 3558 | { | 
|  | 3559 | llvm::raw_svector_ostream Out(MangledName); | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3560 | ABI.getMangleContext().mangleCXXRTTIBaseClassDescriptor( | 
|  | 3561 | Class.RD, Class.OffsetInVBase, VBPtrOffset, OffsetInVBTable, | 
|  | 3562 | Class.Flags, Out); | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3563 | } | 
|  | 3564 |  | 
| David Majnemer | 26a90f8 | 2014-07-07 15:29:10 +0000 | [diff] [blame] | 3565 | // Check to see if we've already declared this object. | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3566 | if (auto BCD = Module.getNamedGlobal(MangledName)) | 
|  | 3567 | return BCD; | 
|  | 3568 |  | 
|  | 3569 | // Forward-declare the base class descriptor. | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3570 | auto Type = ABI.getBaseClassDescriptorType(); | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 3571 | auto BCD = | 
|  | 3572 | new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage, | 
| Yaron Keren | 2c07cc7 | 2015-12-01 08:14:39 +0000 | [diff] [blame] | 3573 | /*Initializer=*/nullptr, MangledName); | 
| Rafael Espindola | 654542a | 2015-01-16 19:23:42 +0000 | [diff] [blame] | 3574 | if (BCD->isWeakForLinker()) | 
|  | 3575 | BCD->setComdat(CGM.getModule().getOrInsertComdat(BCD->getName())); | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3576 |  | 
|  | 3577 | // Initialize the BaseClassDescriptor. | 
|  | 3578 | llvm::Constant *Fields[] = { | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3579 | ABI.getImageRelativeConstant( | 
| David Majnemer | 443250f | 2015-03-17 20:35:00 +0000 | [diff] [blame] | 3580 | ABI.getAddrOfRTTIDescriptor(Context.getTypeDeclType(Class.RD))), | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3581 | llvm::ConstantInt::get(CGM.IntTy, Class.NumBases), | 
|  | 3582 | llvm::ConstantInt::get(CGM.IntTy, Class.OffsetInVBase), | 
|  | 3583 | llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset), | 
|  | 3584 | llvm::ConstantInt::get(CGM.IntTy, OffsetInVBTable), | 
|  | 3585 | llvm::ConstantInt::get(CGM.IntTy, Class.Flags), | 
|  | 3586 | ABI.getImageRelativeConstant( | 
|  | 3587 | MSRTTIBuilder(ABI, Class.RD).getClassHierarchyDescriptor()), | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3588 | }; | 
|  | 3589 | BCD->setInitializer(llvm::ConstantStruct::get(Type, Fields)); | 
|  | 3590 | return BCD; | 
|  | 3591 | } | 
|  | 3592 |  | 
|  | 3593 | llvm::GlobalVariable * | 
|  | 3594 | MSRTTIBuilder::getCompleteObjectLocator(const VPtrInfo *Info) { | 
|  | 3595 | SmallString<256> MangledName; | 
|  | 3596 | { | 
|  | 3597 | llvm::raw_svector_ostream Out(MangledName); | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3598 | ABI.getMangleContext().mangleCXXRTTICompleteObjectLocator(RD, Info->MangledPath, Out); | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3599 | } | 
|  | 3600 |  | 
|  | 3601 | // Check to see if we've already computed this complete object locator. | 
|  | 3602 | if (auto COL = Module.getNamedGlobal(MangledName)) | 
|  | 3603 | return COL; | 
|  | 3604 |  | 
|  | 3605 | // Compute the fields of the complete object locator. | 
|  | 3606 | int OffsetToTop = Info->FullOffsetInMDC.getQuantity(); | 
|  | 3607 | int VFPtrOffset = 0; | 
|  | 3608 | // The offset includes the vtordisp if one exists. | 
|  | 3609 | if (const CXXRecordDecl *VBase = Info->getVBaseWithVPtr()) | 
|  | 3610 | if (Context.getASTRecordLayout(RD) | 
|  | 3611 | .getVBaseOffsetsMap() | 
|  | 3612 | .find(VBase) | 
|  | 3613 | ->second.hasVtorDisp()) | 
|  | 3614 | VFPtrOffset = Info->NonVirtualOffset.getQuantity() + 4; | 
|  | 3615 |  | 
|  | 3616 | // Forward-declare the complete object locator. | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3617 | llvm::StructType *Type = ABI.getCompleteObjectLocatorType(); | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3618 | auto COL = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage, | 
| Yaron Keren | 2c07cc7 | 2015-12-01 08:14:39 +0000 | [diff] [blame] | 3619 | /*Initializer=*/nullptr, MangledName); | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3620 |  | 
|  | 3621 | // Initialize the CompleteObjectLocator. | 
|  | 3622 | llvm::Constant *Fields[] = { | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3623 | llvm::ConstantInt::get(CGM.IntTy, ABI.isImageRelative()), | 
|  | 3624 | llvm::ConstantInt::get(CGM.IntTy, OffsetToTop), | 
|  | 3625 | llvm::ConstantInt::get(CGM.IntTy, VFPtrOffset), | 
|  | 3626 | ABI.getImageRelativeConstant( | 
|  | 3627 | CGM.GetAddrOfRTTIDescriptor(Context.getTypeDeclType(RD))), | 
|  | 3628 | ABI.getImageRelativeConstant(getClassHierarchyDescriptor()), | 
|  | 3629 | ABI.getImageRelativeConstant(COL), | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3630 | }; | 
|  | 3631 | llvm::ArrayRef<llvm::Constant *> FieldsRef(Fields); | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3632 | if (!ABI.isImageRelative()) | 
|  | 3633 | FieldsRef = FieldsRef.drop_back(); | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3634 | COL->setInitializer(llvm::ConstantStruct::get(Type, FieldsRef)); | 
| Rafael Espindola | 654542a | 2015-01-16 19:23:42 +0000 | [diff] [blame] | 3635 | if (COL->isWeakForLinker()) | 
|  | 3636 | COL->setComdat(CGM.getModule().getOrInsertComdat(COL->getName())); | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3637 | return COL; | 
|  | 3638 | } | 
|  | 3639 |  | 
| David Majnemer | ad803d4 | 2015-03-15 07:10:01 +0000 | [diff] [blame] | 3640 | static QualType decomposeTypeForEH(ASTContext &Context, QualType T, | 
|  | 3641 | bool &IsConst, bool &IsVolatile) { | 
|  | 3642 | T = Context.getExceptionObjectType(T); | 
|  | 3643 |  | 
|  | 3644 | // C++14 [except.handle]p3: | 
|  | 3645 | //   A handler is a match for an exception object of type E if [...] | 
|  | 3646 | //     - the handler is of type cv T or const T& where T is a pointer type and | 
|  | 3647 | //       E is a pointer type that can be converted to T by [...] | 
|  | 3648 | //         - a qualification conversion | 
|  | 3649 | IsConst = false; | 
|  | 3650 | IsVolatile = false; | 
|  | 3651 | QualType PointeeType = T->getPointeeType(); | 
|  | 3652 | if (!PointeeType.isNull()) { | 
|  | 3653 | IsConst = PointeeType.isConstQualified(); | 
|  | 3654 | IsVolatile = PointeeType.isVolatileQualified(); | 
|  | 3655 | } | 
|  | 3656 |  | 
|  | 3657 | // Member pointer types like "const int A::*" are represented by having RTTI | 
|  | 3658 | // for "int A::*" and separately storing the const qualifier. | 
|  | 3659 | if (const auto *MPTy = T->getAs<MemberPointerType>()) | 
|  | 3660 | T = Context.getMemberPointerType(PointeeType.getUnqualifiedType(), | 
|  | 3661 | MPTy->getClass()); | 
|  | 3662 |  | 
|  | 3663 | // Pointer types like "const int * const *" are represented by having RTTI | 
|  | 3664 | // for "const int **" and separately storing the const qualifier. | 
|  | 3665 | if (T->isPointerType()) | 
|  | 3666 | T = Context.getPointerType(PointeeType.getUnqualifiedType()); | 
|  | 3667 |  | 
|  | 3668 | return T; | 
|  | 3669 | } | 
|  | 3670 |  | 
| Reid Kleckner | 10aa770 | 2015-09-16 20:15:55 +0000 | [diff] [blame] | 3671 | CatchTypeInfo | 
| David Majnemer | 37b417f | 2015-03-29 21:55:10 +0000 | [diff] [blame] | 3672 | MicrosoftCXXABI::getAddrOfCXXCatchHandlerType(QualType Type, | 
|  | 3673 | QualType CatchHandlerType) { | 
| David Majnemer | 5f0dd61 | 2015-03-17 20:35:05 +0000 | [diff] [blame] | 3674 | // TypeDescriptors for exceptions never have qualified pointer types, | 
| David Majnemer | 443250f | 2015-03-17 20:35:00 +0000 | [diff] [blame] | 3675 | // qualifiers are stored seperately in order to support qualification | 
|  | 3676 | // conversions. | 
|  | 3677 | bool IsConst, IsVolatile; | 
|  | 3678 | Type = decomposeTypeForEH(getContext(), Type, IsConst, IsVolatile); | 
|  | 3679 |  | 
| David Majnemer | 5f0dd61 | 2015-03-17 20:35:05 +0000 | [diff] [blame] | 3680 | bool IsReference = CatchHandlerType->isReferenceType(); | 
|  | 3681 |  | 
| David Majnemer | 5f0dd61 | 2015-03-17 20:35:05 +0000 | [diff] [blame] | 3682 | uint32_t Flags = 0; | 
|  | 3683 | if (IsConst) | 
|  | 3684 | Flags |= 1; | 
|  | 3685 | if (IsVolatile) | 
|  | 3686 | Flags |= 2; | 
|  | 3687 | if (IsReference) | 
|  | 3688 | Flags |= 8; | 
|  | 3689 |  | 
| Reid Kleckner | 10aa770 | 2015-09-16 20:15:55 +0000 | [diff] [blame] | 3690 | return CatchTypeInfo{getAddrOfRTTIDescriptor(Type)->stripPointerCasts(), | 
|  | 3691 | Flags}; | 
| David Majnemer | 443250f | 2015-03-17 20:35:00 +0000 | [diff] [blame] | 3692 | } | 
|  | 3693 |  | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3694 | /// \brief Gets a TypeDescriptor.  Returns a llvm::Constant * rather than a | 
|  | 3695 | /// llvm::GlobalVariable * because different type descriptors have different | 
|  | 3696 | /// types, and need to be abstracted.  They are abstracting by casting the | 
|  | 3697 | /// address to an Int8PtrTy. | 
| David Majnemer | 443250f | 2015-03-17 20:35:00 +0000 | [diff] [blame] | 3698 | llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType Type) { | 
| David Majnemer | 5f0dd61 | 2015-03-17 20:35:05 +0000 | [diff] [blame] | 3699 | SmallString<256> MangledName; | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3700 | { | 
|  | 3701 | llvm::raw_svector_ostream Out(MangledName); | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3702 | getMangleContext().mangleCXXRTTI(Type, Out); | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3703 | } | 
|  | 3704 |  | 
|  | 3705 | // Check to see if we've already declared this TypeDescriptor. | 
|  | 3706 | if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName)) | 
|  | 3707 | return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy); | 
|  | 3708 |  | 
|  | 3709 | // Compute the fields for the TypeDescriptor. | 
| David Majnemer | 5f0dd61 | 2015-03-17 20:35:05 +0000 | [diff] [blame] | 3710 | SmallString<256> TypeInfoString; | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3711 | { | 
|  | 3712 | llvm::raw_svector_ostream Out(TypeInfoString); | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3713 | getMangleContext().mangleCXXRTTIName(Type, Out); | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3714 | } | 
|  | 3715 |  | 
|  | 3716 | // Declare and initialize the TypeDescriptor. | 
|  | 3717 | llvm::Constant *Fields[] = { | 
|  | 3718 | getTypeInfoVTable(CGM),                        // VFPtr | 
|  | 3719 | llvm::ConstantPointerNull::get(CGM.Int8PtrTy), // Runtime data | 
|  | 3720 | llvm::ConstantDataArray::getString(CGM.getLLVMContext(), TypeInfoString)}; | 
|  | 3721 | llvm::StructType *TypeDescriptorType = | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3722 | getTypeDescriptorType(TypeInfoString); | 
| Rafael Espindola | 654542a | 2015-01-16 19:23:42 +0000 | [diff] [blame] | 3723 | auto *Var = new llvm::GlobalVariable( | 
|  | 3724 | CGM.getModule(), TypeDescriptorType, /*Constant=*/false, | 
|  | 3725 | getLinkageForRTTI(Type), | 
|  | 3726 | llvm::ConstantStruct::get(TypeDescriptorType, Fields), | 
| Yaron Keren | 2c07cc7 | 2015-12-01 08:14:39 +0000 | [diff] [blame] | 3727 | MangledName); | 
| Rafael Espindola | 654542a | 2015-01-16 19:23:42 +0000 | [diff] [blame] | 3728 | if (Var->isWeakForLinker()) | 
|  | 3729 | Var->setComdat(CGM.getModule().getOrInsertComdat(Var->getName())); | 
|  | 3730 | return llvm::ConstantExpr::getBitCast(Var, CGM.Int8PtrTy); | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3731 | } | 
|  | 3732 |  | 
|  | 3733 | /// \brief Gets or a creates a Microsoft CompleteObjectLocator. | 
|  | 3734 | llvm::GlobalVariable * | 
|  | 3735 | MicrosoftCXXABI::getMSCompleteObjectLocator(const CXXRecordDecl *RD, | 
|  | 3736 | const VPtrInfo *Info) { | 
| David Majnemer | 611cdb9 | 2014-07-07 08:09:15 +0000 | [diff] [blame] | 3737 | return MSRTTIBuilder(*this, RD).getCompleteObjectLocator(Info); | 
| David Majnemer | e2cb8d1 | 2014-07-07 06:20:47 +0000 | [diff] [blame] | 3738 | } | 
| Rafael Espindola | 91f68b4 | 2014-09-15 19:20:10 +0000 | [diff] [blame] | 3739 |  | 
|  | 3740 | static void emitCXXConstructor(CodeGenModule &CGM, | 
|  | 3741 | const CXXConstructorDecl *ctor, | 
|  | 3742 | StructorType ctorType) { | 
| Rafael Espindola | d48b51b | 2014-09-15 19:24:44 +0000 | [diff] [blame] | 3743 | // There are no constructor variants, always emit the complete destructor. | 
| Rafael Espindola | 694cb5d | 2015-01-16 15:37:11 +0000 | [diff] [blame] | 3744 | llvm::Function *Fn = CGM.codegenCXXStructor(ctor, StructorType::Complete); | 
|  | 3745 | CGM.maybeSetTrivialComdat(*ctor, *Fn); | 
| Rafael Espindola | 91f68b4 | 2014-09-15 19:20:10 +0000 | [diff] [blame] | 3746 | } | 
|  | 3747 |  | 
|  | 3748 | static void emitCXXDestructor(CodeGenModule &CGM, const CXXDestructorDecl *dtor, | 
|  | 3749 | StructorType dtorType) { | 
|  | 3750 | // The complete destructor is equivalent to the base destructor for | 
|  | 3751 | // classes with no virtual bases, so try to emit it as an alias. | 
|  | 3752 | if (!dtor->getParent()->getNumVBases() && | 
|  | 3753 | (dtorType == StructorType::Complete || dtorType == StructorType::Base)) { | 
|  | 3754 | bool ProducedAlias = !CGM.TryEmitDefinitionAsAlias( | 
|  | 3755 | GlobalDecl(dtor, Dtor_Complete), GlobalDecl(dtor, Dtor_Base), true); | 
|  | 3756 | if (ProducedAlias) { | 
|  | 3757 | if (dtorType == StructorType::Complete) | 
|  | 3758 | return; | 
|  | 3759 | if (dtor->isVirtual()) | 
|  | 3760 | CGM.getVTables().EmitThunks(GlobalDecl(dtor, Dtor_Complete)); | 
|  | 3761 | } | 
|  | 3762 | } | 
|  | 3763 |  | 
|  | 3764 | // The base destructor is equivalent to the base destructor of its | 
|  | 3765 | // base class if there is exactly one non-virtual base class with a | 
|  | 3766 | // non-trivial destructor, there are no fields with a non-trivial | 
|  | 3767 | // destructor, and the body of the destructor is trivial. | 
|  | 3768 | if (dtorType == StructorType::Base && !CGM.TryEmitBaseDestructorAsAlias(dtor)) | 
|  | 3769 | return; | 
|  | 3770 |  | 
| Rafael Espindola | 694cb5d | 2015-01-16 15:37:11 +0000 | [diff] [blame] | 3771 | llvm::Function *Fn = CGM.codegenCXXStructor(dtor, dtorType); | 
| Rafael Espindola | d3e0469 | 2015-01-17 01:47:39 +0000 | [diff] [blame] | 3772 | if (Fn->isWeakForLinker()) | 
|  | 3773 | Fn->setComdat(CGM.getModule().getOrInsertComdat(Fn->getName())); | 
| Rafael Espindola | 91f68b4 | 2014-09-15 19:20:10 +0000 | [diff] [blame] | 3774 | } | 
|  | 3775 |  | 
|  | 3776 | void MicrosoftCXXABI::emitCXXStructor(const CXXMethodDecl *MD, | 
|  | 3777 | StructorType Type) { | 
|  | 3778 | if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) { | 
|  | 3779 | emitCXXConstructor(CGM, CD, Type); | 
|  | 3780 | return; | 
|  | 3781 | } | 
|  | 3782 | emitCXXDestructor(CGM, cast<CXXDestructorDecl>(MD), Type); | 
|  | 3783 | } | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 3784 |  | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 3785 | llvm::Function * | 
| David Majnemer | 37fd66e | 2015-03-13 22:36:55 +0000 | [diff] [blame] | 3786 | MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD, | 
|  | 3787 | CXXCtorType CT) { | 
|  | 3788 | assert(CT == Ctor_CopyingClosure || CT == Ctor_DefaultClosure); | 
|  | 3789 |  | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 3790 | // Calculate the mangled name. | 
|  | 3791 | SmallString<256> ThunkName; | 
|  | 3792 | llvm::raw_svector_ostream Out(ThunkName); | 
| David Majnemer | 37fd66e | 2015-03-13 22:36:55 +0000 | [diff] [blame] | 3793 | getMangleContext().mangleCXXCtor(CD, CT, Out); | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 3794 |  | 
|  | 3795 | // If the thunk has been generated previously, just return it. | 
|  | 3796 | if (llvm::GlobalValue *GV = CGM.getModule().getNamedValue(ThunkName)) | 
|  | 3797 | return cast<llvm::Function>(GV); | 
|  | 3798 |  | 
|  | 3799 | // Create the llvm::Function. | 
| David Majnemer | 37fd66e | 2015-03-13 22:36:55 +0000 | [diff] [blame] | 3800 | const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeMSCtorClosure(CD, CT); | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 3801 | llvm::FunctionType *ThunkTy = CGM.getTypes().GetFunctionType(FnInfo); | 
|  | 3802 | const CXXRecordDecl *RD = CD->getParent(); | 
|  | 3803 | QualType RecordTy = getContext().getRecordType(RD); | 
|  | 3804 | llvm::Function *ThunkFn = llvm::Function::Create( | 
|  | 3805 | ThunkTy, getLinkageForRTTI(RecordTy), ThunkName.str(), &CGM.getModule()); | 
| Reid Kleckner | bba3cb9 | 2015-03-17 19:00:50 +0000 | [diff] [blame] | 3806 | ThunkFn->setCallingConv(static_cast<llvm::CallingConv::ID>( | 
|  | 3807 | FnInfo.getEffectiveCallingConvention())); | 
| David Majnemer | 63aa2fb | 2015-06-30 21:23:51 +0000 | [diff] [blame] | 3808 | if (ThunkFn->isWeakForLinker()) | 
|  | 3809 | ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName())); | 
| David Majnemer | 37fd66e | 2015-03-13 22:36:55 +0000 | [diff] [blame] | 3810 | bool IsCopy = CT == Ctor_CopyingClosure; | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 3811 |  | 
|  | 3812 | // Start codegen. | 
|  | 3813 | CodeGenFunction CGF(CGM); | 
|  | 3814 | CGF.CurGD = GlobalDecl(CD, Ctor_Complete); | 
|  | 3815 |  | 
|  | 3816 | // Build FunctionArgs. | 
|  | 3817 | FunctionArgList FunctionArgs; | 
|  | 3818 |  | 
| David Majnemer | 37fd66e | 2015-03-13 22:36:55 +0000 | [diff] [blame] | 3819 | // A constructor always starts with a 'this' pointer as its first argument. | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 3820 | buildThisParam(CGF, FunctionArgs); | 
|  | 3821 |  | 
|  | 3822 | // Following the 'this' pointer is a reference to the source object that we | 
|  | 3823 | // are copying from. | 
|  | 3824 | ImplicitParamDecl SrcParam( | 
|  | 3825 | getContext(), nullptr, SourceLocation(), &getContext().Idents.get("src"), | 
|  | 3826 | getContext().getLValueReferenceType(RecordTy, | 
|  | 3827 | /*SpelledAsLValue=*/true)); | 
| David Majnemer | 37fd66e | 2015-03-13 22:36:55 +0000 | [diff] [blame] | 3828 | if (IsCopy) | 
|  | 3829 | FunctionArgs.push_back(&SrcParam); | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 3830 |  | 
| David Majnemer | 37fd66e | 2015-03-13 22:36:55 +0000 | [diff] [blame] | 3831 | // Constructors for classes which utilize virtual bases have an additional | 
|  | 3832 | // parameter which indicates whether or not it is being delegated to by a more | 
|  | 3833 | // derived constructor. | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 3834 | ImplicitParamDecl IsMostDerived(getContext(), nullptr, SourceLocation(), | 
|  | 3835 | &getContext().Idents.get("is_most_derived"), | 
|  | 3836 | getContext().IntTy); | 
|  | 3837 | // Only add the parameter to the list if thie class has virtual bases. | 
|  | 3838 | if (RD->getNumVBases() > 0) | 
|  | 3839 | FunctionArgs.push_back(&IsMostDerived); | 
|  | 3840 |  | 
|  | 3841 | // Start defining the function. | 
|  | 3842 | CGF.StartFunction(GlobalDecl(), FnInfo.getReturnType(), ThunkFn, FnInfo, | 
|  | 3843 | FunctionArgs, CD->getLocation(), SourceLocation()); | 
|  | 3844 | EmitThisParam(CGF); | 
|  | 3845 | llvm::Value *This = getThisValue(CGF); | 
|  | 3846 |  | 
|  | 3847 | llvm::Value *SrcVal = | 
| David Majnemer | 37fd66e | 2015-03-13 22:36:55 +0000 | [diff] [blame] | 3848 | IsCopy ? CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&SrcParam), "src") | 
|  | 3849 | : nullptr; | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 3850 |  | 
|  | 3851 | CallArgList Args; | 
|  | 3852 |  | 
|  | 3853 | // Push the this ptr. | 
|  | 3854 | Args.add(RValue::get(This), CD->getThisType(getContext())); | 
|  | 3855 |  | 
|  | 3856 | // Push the src ptr. | 
| David Majnemer | 37fd66e | 2015-03-13 22:36:55 +0000 | [diff] [blame] | 3857 | if (SrcVal) | 
|  | 3858 | Args.add(RValue::get(SrcVal), SrcParam.getType()); | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 3859 |  | 
|  | 3860 | // Add the rest of the default arguments. | 
|  | 3861 | std::vector<Stmt *> ArgVec; | 
| Reid Kleckner | 93f661a | 2015-03-17 21:51:43 +0000 | [diff] [blame] | 3862 | for (unsigned I = IsCopy ? 1 : 0, E = CD->getNumParams(); I != E; ++I) { | 
|  | 3863 | Stmt *DefaultArg = getContext().getDefaultArgExprForConstructor(CD, I); | 
|  | 3864 | assert(DefaultArg && "sema forgot to instantiate default args"); | 
|  | 3865 | ArgVec.push_back(DefaultArg); | 
|  | 3866 | } | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 3867 |  | 
|  | 3868 | CodeGenFunction::RunCleanupsScope Cleanups(CGF); | 
|  | 3869 |  | 
|  | 3870 | const auto *FPT = CD->getType()->castAs<FunctionProtoType>(); | 
| David Blaikie | f05779e | 2015-07-21 18:37:18 +0000 | [diff] [blame] | 3871 | CGF.EmitCallArgs(Args, FPT, llvm::makeArrayRef(ArgVec), CD, IsCopy ? 1 : 0); | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 3872 |  | 
|  | 3873 | // Insert any ABI-specific implicit constructor arguments. | 
|  | 3874 | unsigned ExtraArgs = addImplicitConstructorArgs(CGF, CD, Ctor_Complete, | 
|  | 3875 | /*ForVirtualBase=*/false, | 
|  | 3876 | /*Delegating=*/false, Args); | 
|  | 3877 |  | 
|  | 3878 | // Call the destructor with our arguments. | 
|  | 3879 | llvm::Value *CalleeFn = CGM.getAddrOfCXXStructor(CD, StructorType::Complete); | 
|  | 3880 | const CGFunctionInfo &CalleeInfo = CGM.getTypes().arrangeCXXConstructorCall( | 
|  | 3881 | Args, CD, Ctor_Complete, ExtraArgs); | 
|  | 3882 | CGF.EmitCall(CalleeInfo, CalleeFn, ReturnValueSlot(), Args, CD); | 
|  | 3883 |  | 
|  | 3884 | Cleanups.ForceCleanup(); | 
|  | 3885 |  | 
|  | 3886 | // Emit the ret instruction, remove any temporary instructions created for the | 
|  | 3887 | // aid of CodeGen. | 
|  | 3888 | CGF.FinishFunction(SourceLocation()); | 
|  | 3889 |  | 
|  | 3890 | return ThunkFn; | 
|  | 3891 | } | 
|  | 3892 |  | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 3893 | llvm::Constant *MicrosoftCXXABI::getCatchableType(QualType T, | 
|  | 3894 | uint32_t NVOffset, | 
|  | 3895 | int32_t VBPtrOffset, | 
|  | 3896 | uint32_t VBIndex) { | 
|  | 3897 | assert(!T->isReferenceType()); | 
|  | 3898 |  | 
| David Majnemer | e7a818f | 2015-03-06 18:53:55 +0000 | [diff] [blame] | 3899 | CXXRecordDecl *RD = T->getAsCXXRecordDecl(); | 
|  | 3900 | const CXXConstructorDecl *CD = | 
|  | 3901 | RD ? CGM.getContext().getCopyConstructorForExceptionObject(RD) : nullptr; | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 3902 | CXXCtorType CT = Ctor_Complete; | 
| David Majnemer | 37fd66e | 2015-03-13 22:36:55 +0000 | [diff] [blame] | 3903 | if (CD) | 
|  | 3904 | if (!hasDefaultCXXMethodCC(getContext(), CD) || CD->getNumParams() != 1) | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 3905 | CT = Ctor_CopyingClosure; | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 3906 |  | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 3907 | uint32_t Size = getContext().getTypeSizeInChars(T).getQuantity(); | 
|  | 3908 | SmallString<256> MangledName; | 
|  | 3909 | { | 
|  | 3910 | llvm::raw_svector_ostream Out(MangledName); | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 3911 | getMangleContext().mangleCXXCatchableType(T, CD, CT, Size, NVOffset, | 
| David Majnemer | 999cbf9 | 2015-03-10 19:01:51 +0000 | [diff] [blame] | 3912 | VBPtrOffset, VBIndex, Out); | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 3913 | } | 
|  | 3914 | if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName)) | 
|  | 3915 | return getImageRelativeConstant(GV); | 
|  | 3916 |  | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 3917 | // The TypeDescriptor is used by the runtime to determine if a catch handler | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 3918 | // is appropriate for the exception object. | 
| David Majnemer | 443250f | 2015-03-17 20:35:00 +0000 | [diff] [blame] | 3919 | llvm::Constant *TD = getImageRelativeConstant(getAddrOfRTTIDescriptor(T)); | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 3920 |  | 
|  | 3921 | // The runtime is responsible for calling the copy constructor if the | 
|  | 3922 | // exception is caught by value. | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 3923 | llvm::Constant *CopyCtor; | 
|  | 3924 | if (CD) { | 
|  | 3925 | if (CT == Ctor_CopyingClosure) | 
| David Majnemer | 37fd66e | 2015-03-13 22:36:55 +0000 | [diff] [blame] | 3926 | CopyCtor = getAddrOfCXXCtorClosure(CD, Ctor_CopyingClosure); | 
| David Majnemer | dfa6d20 | 2015-03-11 18:36:39 +0000 | [diff] [blame] | 3927 | else | 
|  | 3928 | CopyCtor = CGM.getAddrOfCXXStructor(CD, StructorType::Complete); | 
|  | 3929 |  | 
|  | 3930 | CopyCtor = llvm::ConstantExpr::getBitCast(CopyCtor, CGM.Int8PtrTy); | 
|  | 3931 | } else { | 
|  | 3932 | CopyCtor = llvm::Constant::getNullValue(CGM.Int8PtrTy); | 
|  | 3933 | } | 
| David Majnemer | e7a818f | 2015-03-06 18:53:55 +0000 | [diff] [blame] | 3934 | CopyCtor = getImageRelativeConstant(CopyCtor); | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 3935 |  | 
| David Majnemer | e7a818f | 2015-03-06 18:53:55 +0000 | [diff] [blame] | 3936 | bool IsScalar = !RD; | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 3937 | bool HasVirtualBases = false; | 
|  | 3938 | bool IsStdBadAlloc = false; // std::bad_alloc is special for some reason. | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 3939 | QualType PointeeType = T; | 
|  | 3940 | if (T->isPointerType()) | 
|  | 3941 | PointeeType = T->getPointeeType(); | 
|  | 3942 | if (const CXXRecordDecl *RD = PointeeType->getAsCXXRecordDecl()) { | 
|  | 3943 | HasVirtualBases = RD->getNumVBases() > 0; | 
|  | 3944 | if (IdentifierInfo *II = RD->getIdentifier()) | 
|  | 3945 | IsStdBadAlloc = II->isStr("bad_alloc") && RD->isInStdNamespace(); | 
|  | 3946 | } | 
|  | 3947 |  | 
|  | 3948 | // Encode the relevant CatchableType properties into the Flags bitfield. | 
|  | 3949 | // FIXME: Figure out how bits 2 or 8 can get set. | 
|  | 3950 | uint32_t Flags = 0; | 
|  | 3951 | if (IsScalar) | 
|  | 3952 | Flags |= 1; | 
|  | 3953 | if (HasVirtualBases) | 
|  | 3954 | Flags |= 4; | 
|  | 3955 | if (IsStdBadAlloc) | 
|  | 3956 | Flags |= 16; | 
|  | 3957 |  | 
|  | 3958 | llvm::Constant *Fields[] = { | 
|  | 3959 | llvm::ConstantInt::get(CGM.IntTy, Flags),       // Flags | 
|  | 3960 | TD,                                             // TypeDescriptor | 
|  | 3961 | llvm::ConstantInt::get(CGM.IntTy, NVOffset),    // NonVirtualAdjustment | 
|  | 3962 | llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset), // OffsetToVBPtr | 
|  | 3963 | llvm::ConstantInt::get(CGM.IntTy, VBIndex),     // VBTableIndex | 
|  | 3964 | llvm::ConstantInt::get(CGM.IntTy, Size),        // Size | 
|  | 3965 | CopyCtor                                        // CopyCtor | 
|  | 3966 | }; | 
|  | 3967 | llvm::StructType *CTType = getCatchableTypeType(); | 
|  | 3968 | auto *GV = new llvm::GlobalVariable( | 
|  | 3969 | CGM.getModule(), CTType, /*Constant=*/true, getLinkageForRTTI(T), | 
| Yaron Keren | 2c07cc7 | 2015-12-01 08:14:39 +0000 | [diff] [blame] | 3970 | llvm::ConstantStruct::get(CTType, Fields), MangledName); | 
| David Majnemer | 322fe41 | 2015-03-06 23:45:23 +0000 | [diff] [blame] | 3971 | GV->setUnnamedAddr(true); | 
|  | 3972 | GV->setSection(".xdata"); | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 3973 | if (GV->isWeakForLinker()) | 
|  | 3974 | GV->setComdat(CGM.getModule().getOrInsertComdat(GV->getName())); | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 3975 | return getImageRelativeConstant(GV); | 
|  | 3976 | } | 
|  | 3977 |  | 
|  | 3978 | llvm::GlobalVariable *MicrosoftCXXABI::getCatchableTypeArray(QualType T) { | 
|  | 3979 | assert(!T->isReferenceType()); | 
|  | 3980 |  | 
|  | 3981 | // See if we've already generated a CatchableTypeArray for this type before. | 
|  | 3982 | llvm::GlobalVariable *&CTA = CatchableTypeArrays[T]; | 
|  | 3983 | if (CTA) | 
|  | 3984 | return CTA; | 
|  | 3985 |  | 
|  | 3986 | // Ensure that we don't have duplicate entries in our CatchableTypeArray by | 
|  | 3987 | // using a SmallSetVector.  Duplicates may arise due to virtual bases | 
|  | 3988 | // occurring more than once in the hierarchy. | 
|  | 3989 | llvm::SmallSetVector<llvm::Constant *, 2> CatchableTypes; | 
|  | 3990 |  | 
|  | 3991 | // C++14 [except.handle]p3: | 
|  | 3992 | //   A handler is a match for an exception object of type E if [...] | 
|  | 3993 | //     - the handler is of type cv T or cv T& and T is an unambiguous public | 
|  | 3994 | //       base class of E, or | 
|  | 3995 | //     - the handler is of type cv T or const T& where T is a pointer type and | 
|  | 3996 | //       E is a pointer type that can be converted to T by [...] | 
|  | 3997 | //         - a standard pointer conversion (4.10) not involving conversions to | 
|  | 3998 | //           pointers to private or protected or ambiguous classes | 
|  | 3999 | const CXXRecordDecl *MostDerivedClass = nullptr; | 
|  | 4000 | bool IsPointer = T->isPointerType(); | 
|  | 4001 | if (IsPointer) | 
|  | 4002 | MostDerivedClass = T->getPointeeType()->getAsCXXRecordDecl(); | 
|  | 4003 | else | 
|  | 4004 | MostDerivedClass = T->getAsCXXRecordDecl(); | 
|  | 4005 |  | 
|  | 4006 | // Collect all the unambiguous public bases of the MostDerivedClass. | 
|  | 4007 | if (MostDerivedClass) { | 
| David Majnemer | 9ced3dd | 2015-03-14 23:44:48 +0000 | [diff] [blame] | 4008 | const ASTContext &Context = getContext(); | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 4009 | const ASTRecordLayout &MostDerivedLayout = | 
|  | 4010 | Context.getASTRecordLayout(MostDerivedClass); | 
|  | 4011 | MicrosoftVTableContext &VTableContext = CGM.getMicrosoftVTableContext(); | 
|  | 4012 | SmallVector<MSRTTIClass, 8> Classes; | 
|  | 4013 | serializeClassHierarchy(Classes, MostDerivedClass); | 
|  | 4014 | Classes.front().initialize(/*Parent=*/nullptr, /*Specifier=*/nullptr); | 
|  | 4015 | detectAmbiguousBases(Classes); | 
|  | 4016 | for (const MSRTTIClass &Class : Classes) { | 
|  | 4017 | // Skip any ambiguous or private bases. | 
|  | 4018 | if (Class.Flags & | 
|  | 4019 | (MSRTTIClass::IsPrivateOnPath | MSRTTIClass::IsAmbiguous)) | 
|  | 4020 | continue; | 
|  | 4021 | // Write down how to convert from a derived pointer to a base pointer. | 
|  | 4022 | uint32_t OffsetInVBTable = 0; | 
|  | 4023 | int32_t VBPtrOffset = -1; | 
|  | 4024 | if (Class.VirtualRoot) { | 
|  | 4025 | OffsetInVBTable = | 
|  | 4026 | VTableContext.getVBTableIndex(MostDerivedClass, Class.VirtualRoot)*4; | 
|  | 4027 | VBPtrOffset = MostDerivedLayout.getVBPtrOffset().getQuantity(); | 
|  | 4028 | } | 
|  | 4029 |  | 
|  | 4030 | // Turn our record back into a pointer if the exception object is a | 
|  | 4031 | // pointer. | 
|  | 4032 | QualType RTTITy = QualType(Class.RD->getTypeForDecl(), 0); | 
|  | 4033 | if (IsPointer) | 
|  | 4034 | RTTITy = Context.getPointerType(RTTITy); | 
|  | 4035 | CatchableTypes.insert(getCatchableType(RTTITy, Class.OffsetInVBase, | 
|  | 4036 | VBPtrOffset, OffsetInVBTable)); | 
|  | 4037 | } | 
|  | 4038 | } | 
|  | 4039 |  | 
|  | 4040 | // C++14 [except.handle]p3: | 
|  | 4041 | //   A handler is a match for an exception object of type E if | 
|  | 4042 | //     - The handler is of type cv T or cv T& and E and T are the same type | 
|  | 4043 | //       (ignoring the top-level cv-qualifiers) | 
|  | 4044 | CatchableTypes.insert(getCatchableType(T)); | 
|  | 4045 |  | 
|  | 4046 | // C++14 [except.handle]p3: | 
|  | 4047 | //   A handler is a match for an exception object of type E if | 
|  | 4048 | //     - the handler is of type cv T or const T& where T is a pointer type and | 
|  | 4049 | //       E is a pointer type that can be converted to T by [...] | 
|  | 4050 | //         - a standard pointer conversion (4.10) not involving conversions to | 
|  | 4051 | //           pointers to private or protected or ambiguous classes | 
|  | 4052 | // | 
| David Majnemer | f205f53 | 2015-04-04 05:37:48 +0000 | [diff] [blame] | 4053 | // C++14 [conv.ptr]p2: | 
|  | 4054 | //   A prvalue of type "pointer to cv T," where T is an object type, can be | 
|  | 4055 | //   converted to a prvalue of type "pointer to cv void". | 
|  | 4056 | if (IsPointer && T->getPointeeType()->isObjectType()) | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 4057 | CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy)); | 
|  | 4058 |  | 
| David Majnemer | a1aea9a | 2015-03-12 17:44:49 +0000 | [diff] [blame] | 4059 | // C++14 [except.handle]p3: | 
|  | 4060 | //   A handler is a match for an exception object of type E if [...] | 
|  | 4061 | //     - the handler is of type cv T or const T& where T is a pointer or | 
|  | 4062 | //       pointer to member type and E is std::nullptr_t. | 
|  | 4063 | // | 
|  | 4064 | // We cannot possibly list all possible pointer types here, making this | 
|  | 4065 | // implementation incompatible with the standard.  However, MSVC includes an | 
|  | 4066 | // entry for pointer-to-void in this case.  Let's do the same. | 
|  | 4067 | if (T->isNullPtrType()) | 
|  | 4068 | CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy)); | 
|  | 4069 |  | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 4070 | uint32_t NumEntries = CatchableTypes.size(); | 
|  | 4071 | llvm::Type *CTType = | 
|  | 4072 | getImageRelativeType(getCatchableTypeType()->getPointerTo()); | 
|  | 4073 | llvm::ArrayType *AT = llvm::ArrayType::get(CTType, NumEntries); | 
|  | 4074 | llvm::StructType *CTAType = getCatchableTypeArrayType(NumEntries); | 
|  | 4075 | llvm::Constant *Fields[] = { | 
|  | 4076 | llvm::ConstantInt::get(CGM.IntTy, NumEntries),    // NumEntries | 
|  | 4077 | llvm::ConstantArray::get( | 
|  | 4078 | AT, llvm::makeArrayRef(CatchableTypes.begin(), | 
|  | 4079 | CatchableTypes.end())) // CatchableTypes | 
|  | 4080 | }; | 
|  | 4081 | SmallString<256> MangledName; | 
|  | 4082 | { | 
|  | 4083 | llvm::raw_svector_ostream Out(MangledName); | 
|  | 4084 | getMangleContext().mangleCXXCatchableTypeArray(T, NumEntries, Out); | 
|  | 4085 | } | 
|  | 4086 | CTA = new llvm::GlobalVariable( | 
|  | 4087 | CGM.getModule(), CTAType, /*Constant=*/true, getLinkageForRTTI(T), | 
| Yaron Keren | 2c07cc7 | 2015-12-01 08:14:39 +0000 | [diff] [blame] | 4088 | llvm::ConstantStruct::get(CTAType, Fields), MangledName); | 
| David Majnemer | 322fe41 | 2015-03-06 23:45:23 +0000 | [diff] [blame] | 4089 | CTA->setUnnamedAddr(true); | 
|  | 4090 | CTA->setSection(".xdata"); | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 4091 | if (CTA->isWeakForLinker()) | 
|  | 4092 | CTA->setComdat(CGM.getModule().getOrInsertComdat(CTA->getName())); | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 4093 | return CTA; | 
|  | 4094 | } | 
|  | 4095 |  | 
|  | 4096 | llvm::GlobalVariable *MicrosoftCXXABI::getThrowInfo(QualType T) { | 
| David Majnemer | ad803d4 | 2015-03-15 07:10:01 +0000 | [diff] [blame] | 4097 | bool IsConst, IsVolatile; | 
|  | 4098 | T = decomposeTypeForEH(getContext(), T, IsConst, IsVolatile); | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 4099 |  | 
|  | 4100 | // The CatchableTypeArray enumerates the various (CV-unqualified) types that | 
|  | 4101 | // the exception object may be caught as. | 
|  | 4102 | llvm::GlobalVariable *CTA = getCatchableTypeArray(T); | 
|  | 4103 | // The first field in a CatchableTypeArray is the number of CatchableTypes. | 
|  | 4104 | // This is used as a component of the mangled name which means that we need to | 
|  | 4105 | // know what it is in order to see if we have previously generated the | 
|  | 4106 | // ThrowInfo. | 
|  | 4107 | uint32_t NumEntries = | 
|  | 4108 | cast<llvm::ConstantInt>(CTA->getInitializer()->getAggregateElement(0U)) | 
|  | 4109 | ->getLimitedValue(); | 
|  | 4110 |  | 
|  | 4111 | SmallString<256> MangledName; | 
|  | 4112 | { | 
|  | 4113 | llvm::raw_svector_ostream Out(MangledName); | 
|  | 4114 | getMangleContext().mangleCXXThrowInfo(T, IsConst, IsVolatile, NumEntries, | 
|  | 4115 | Out); | 
|  | 4116 | } | 
|  | 4117 |  | 
|  | 4118 | // Reuse a previously generated ThrowInfo if we have generated an appropriate | 
|  | 4119 | // one before. | 
|  | 4120 | if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName)) | 
|  | 4121 | return GV; | 
|  | 4122 |  | 
|  | 4123 | // The RTTI TypeDescriptor uses an unqualified type but catch clauses must | 
|  | 4124 | // be at least as CV qualified.  Encode this requirement into the Flags | 
|  | 4125 | // bitfield. | 
|  | 4126 | uint32_t Flags = 0; | 
|  | 4127 | if (IsConst) | 
|  | 4128 | Flags |= 1; | 
|  | 4129 | if (IsVolatile) | 
|  | 4130 | Flags |= 2; | 
|  | 4131 |  | 
|  | 4132 | // The cleanup-function (a destructor) must be called when the exception | 
|  | 4133 | // object's lifetime ends. | 
|  | 4134 | llvm::Constant *CleanupFn = llvm::Constant::getNullValue(CGM.Int8PtrTy); | 
|  | 4135 | if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) | 
|  | 4136 | if (CXXDestructorDecl *DtorD = RD->getDestructor()) | 
|  | 4137 | if (!DtorD->isTrivial()) | 
|  | 4138 | CleanupFn = llvm::ConstantExpr::getBitCast( | 
|  | 4139 | CGM.getAddrOfCXXStructor(DtorD, StructorType::Complete), | 
|  | 4140 | CGM.Int8PtrTy); | 
|  | 4141 | // This is unused as far as we can tell, initialize it to null. | 
|  | 4142 | llvm::Constant *ForwardCompat = | 
|  | 4143 | getImageRelativeConstant(llvm::Constant::getNullValue(CGM.Int8PtrTy)); | 
|  | 4144 | llvm::Constant *PointerToCatchableTypes = getImageRelativeConstant( | 
|  | 4145 | llvm::ConstantExpr::getBitCast(CTA, CGM.Int8PtrTy)); | 
|  | 4146 | llvm::StructType *TIType = getThrowInfoType(); | 
|  | 4147 | llvm::Constant *Fields[] = { | 
|  | 4148 | llvm::ConstantInt::get(CGM.IntTy, Flags), // Flags | 
|  | 4149 | getImageRelativeConstant(CleanupFn),      // CleanupFn | 
|  | 4150 | ForwardCompat,                            // ForwardCompat | 
|  | 4151 | PointerToCatchableTypes                   // CatchableTypeArray | 
|  | 4152 | }; | 
|  | 4153 | auto *GV = new llvm::GlobalVariable( | 
|  | 4154 | CGM.getModule(), TIType, /*Constant=*/true, getLinkageForRTTI(T), | 
|  | 4155 | llvm::ConstantStruct::get(TIType, Fields), StringRef(MangledName)); | 
| David Majnemer | 322fe41 | 2015-03-06 23:45:23 +0000 | [diff] [blame] | 4156 | GV->setUnnamedAddr(true); | 
|  | 4157 | GV->setSection(".xdata"); | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 4158 | if (GV->isWeakForLinker()) | 
|  | 4159 | GV->setComdat(CGM.getModule().getOrInsertComdat(GV->getName())); | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 4160 | return GV; | 
|  | 4161 | } | 
|  | 4162 |  | 
|  | 4163 | void MicrosoftCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) { | 
|  | 4164 | const Expr *SubExpr = E->getSubExpr(); | 
|  | 4165 | QualType ThrowType = SubExpr->getType(); | 
|  | 4166 | // The exception object lives on the stack and it's address is passed to the | 
|  | 4167 | // runtime function. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 4168 | Address AI = CGF.CreateMemTemp(ThrowType); | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 4169 | CGF.EmitAnyExprToMem(SubExpr, AI, ThrowType.getQualifiers(), | 
|  | 4170 | /*IsInit=*/true); | 
|  | 4171 |  | 
|  | 4172 | // The so-called ThrowInfo is used to describe how the exception object may be | 
|  | 4173 | // caught. | 
|  | 4174 | llvm::GlobalVariable *TI = getThrowInfo(ThrowType); | 
|  | 4175 |  | 
|  | 4176 | // Call into the runtime to throw the exception. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 4177 | llvm::Value *Args[] = { | 
|  | 4178 | CGF.Builder.CreateBitCast(AI.getPointer(), CGM.Int8PtrTy), | 
|  | 4179 | TI | 
|  | 4180 | }; | 
| David Majnemer | 7c23707 | 2015-03-05 00:46:22 +0000 | [diff] [blame] | 4181 | CGF.EmitNoreturnRuntimeCallOrInvoke(getThrowFn(), Args); | 
|  | 4182 | } |