1 //===----- CGCXXABI.cpp - Interface to C++ ABIs ---------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This provides an abstract class for C++ code generation. Concrete subclasses 10 // of this implement code generation for specific C++ ABIs. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "CGCXXABI.h" 15 #include "CGCleanup.h" 16 #include "clang/AST/Attr.h" 17 18 using namespace clang; 19 using namespace CodeGen; 20 21 CGCXXABI::~CGCXXABI() { } 22 23 void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) { 24 DiagnosticsEngine &Diags = CGF.CGM.getDiags(); 25 unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, 26 "cannot yet compile %0 in this ABI"); 27 Diags.Report(CGF.getContext().getFullLoc(CGF.CurCodeDecl->getLocation()), 28 DiagID) 29 << S; 30 } 31 32 llvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) { 33 return llvm::Constant::getNullValue(CGM.getTypes().ConvertType(T)); 34 } 35 36 llvm::Type * 37 CGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) { 38 return CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType()); 39 } 40 41 CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer( 42 CodeGenFunction &CGF, const Expr *E, Address This, 43 llvm::Value *&ThisPtrForCall, 44 llvm::Value *MemPtr, const MemberPointerType *MPT) { 45 ErrorUnsupportedABI(CGF, "calls through member pointers"); 46 47 ThisPtrForCall = This.getPointer(); 48 const FunctionProtoType *FPT = 49 MPT->getPointeeType()->getAs<FunctionProtoType>(); 50 const auto *RD = 51 cast<CXXRecordDecl>(MPT->getClass()->castAs<RecordType>()->getDecl()); 52 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType( 53 CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr)); 54 llvm::Constant *FnPtr = llvm::Constant::getNullValue(FTy->getPointerTo()); 55 return CGCallee::forDirect(FnPtr, FPT); 56 } 57 58 llvm::Value * 59 CGCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E, 60 Address Base, llvm::Value *MemPtr, 61 const MemberPointerType *MPT) { 62 ErrorUnsupportedABI(CGF, "loads of member pointers"); 63 llvm::Type *Ty = CGF.ConvertType(MPT->getPointeeType()) 64 ->getPointerTo(Base.getAddressSpace()); 65 return llvm::Constant::getNullValue(Ty); 66 } 67 68 llvm::Value *CGCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, 69 const CastExpr *E, 70 llvm::Value *Src) { 71 ErrorUnsupportedABI(CGF, "member function pointer conversions"); 72 return GetBogusMemberPointer(E->getType()); 73 } 74 75 llvm::Constant *CGCXXABI::EmitMemberPointerConversion(const CastExpr *E, 76 llvm::Constant *Src) { 77 return GetBogusMemberPointer(E->getType()); 78 } 79 80 llvm::Value * 81 CGCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF, 82 llvm::Value *L, 83 llvm::Value *R, 84 const MemberPointerType *MPT, 85 bool Inequality) { 86 ErrorUnsupportedABI(CGF, "member function pointer comparison"); 87 return CGF.Builder.getFalse(); 88 } 89 90 llvm::Value * 91 CGCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF, 92 llvm::Value *MemPtr, 93 const MemberPointerType *MPT) { 94 ErrorUnsupportedABI(CGF, "member function pointer null testing"); 95 return CGF.Builder.getFalse(); 96 } 97 98 llvm::Constant * 99 CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { 100 return GetBogusMemberPointer(QualType(MPT, 0)); 101 } 102 103 llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { 104 return GetBogusMemberPointer(CGM.getContext().getMemberPointerType( 105 MD->getType(), MD->getParent()->getTypeForDecl())); 106 } 107 108 llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, 109 CharUnits offset) { 110 return GetBogusMemberPointer(QualType(MPT, 0)); 111 } 112 113 llvm::Constant *CGCXXABI::EmitMemberPointer(const APValue &MP, QualType MPT) { 114 return GetBogusMemberPointer(MPT); 115 } 116 117 bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) { 118 // Fake answer. 119 return true; 120 } 121 122 void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList ¶ms) { 123 const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); 124 125 // FIXME: I'm not entirely sure I like using a fake decl just for code 126 // generation. Maybe we can come up with a better way? 127 auto *ThisDecl = ImplicitParamDecl::Create( 128 CGM.getContext(), nullptr, MD->getLocation(), 129 &CGM.getContext().Idents.get("this"), MD->getThisType(), 130 ImplicitParamDecl::CXXThis); 131 params.push_back(ThisDecl); 132 CGF.CXXABIThisDecl = ThisDecl; 133 134 // Compute the presumed alignment of 'this', which basically comes 135 // down to whether we know it's a complete object or not. 136 auto &Layout = CGF.getContext().getASTRecordLayout(MD->getParent()); 137 if (MD->getParent()->getNumVBases() == 0 || // avoid vcall in common case 138 MD->getParent()->hasAttr<FinalAttr>() || 139 !isThisCompleteObject(CGF.CurGD)) { 140 CGF.CXXABIThisAlignment = Layout.getAlignment(); 141 } else { 142 CGF.CXXABIThisAlignment = Layout.getNonVirtualAlignment(); 143 } 144 } 145 146 llvm::Value *CGCXXABI::loadIncomingCXXThis(CodeGenFunction &CGF) { 147 return CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)), 148 "this"); 149 } 150 151 void CGCXXABI::setCXXABIThisValue(CodeGenFunction &CGF, llvm::Value *ThisPtr) { 152 /// Initialize the 'this' slot. 153 assert(getThisDecl(CGF) && "no 'this' variable for function"); 154 CGF.CXXABIThisValue = ThisPtr; 155 } 156 157 void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, 158 RValue RV, QualType ResultType) { 159 CGF.EmitReturnOfRValue(RV, ResultType); 160 } 161 162 CharUnits CGCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { 163 if (!requiresArrayCookie(expr)) 164 return CharUnits::Zero(); 165 return getArrayCookieSizeImpl(expr->getAllocatedType()); 166 } 167 168 CharUnits CGCXXABI::getArrayCookieSizeImpl(QualType elementType) { 169 // BOGUS 170 return CharUnits::Zero(); 171 } 172 173 Address CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, 174 Address NewPtr, 175 llvm::Value *NumElements, 176 const CXXNewExpr *expr, 177 QualType ElementType) { 178 // Should never be called. 179 ErrorUnsupportedABI(CGF, "array cookie initialization"); 180 return Address::invalid(); 181 } 182 183 bool CGCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr, 184 QualType elementType) { 185 // If the class's usual deallocation function takes two arguments, 186 // it needs a cookie. 187 if (expr->doesUsualArrayDeleteWantSize()) 188 return true; 189 190 return elementType.isDestructedType(); 191 } 192 193 bool CGCXXABI::requiresArrayCookie(const CXXNewExpr *expr) { 194 // If the class's usual deallocation function takes two arguments, 195 // it needs a cookie. 196 if (expr->doesUsualArrayDeleteWantSize()) 197 return true; 198 199 return expr->getAllocatedType().isDestructedType(); 200 } 201 202 void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr, 203 const CXXDeleteExpr *expr, QualType eltTy, 204 llvm::Value *&numElements, 205 llvm::Value *&allocPtr, CharUnits &cookieSize) { 206 // Derive a char* in the same address space as the pointer. 207 ptr = CGF.Builder.CreateElementBitCast(ptr, CGF.Int8Ty); 208 209 // If we don't need an array cookie, bail out early. 210 if (!requiresArrayCookie(expr, eltTy)) { 211 allocPtr = ptr.getPointer(); 212 numElements = nullptr; 213 cookieSize = CharUnits::Zero(); 214 return; 215 } 216 217 cookieSize = getArrayCookieSizeImpl(eltTy); 218 Address allocAddr = 219 CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize); 220 allocPtr = allocAddr.getPointer(); 221 numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize); 222 } 223 224 llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, 225 Address ptr, 226 CharUnits cookieSize) { 227 ErrorUnsupportedABI(CGF, "reading a new[] cookie"); 228 return llvm::ConstantInt::get(CGF.SizeTy, 0); 229 } 230 231 /// Returns the adjustment, in bytes, required for the given 232 /// member-pointer operation. Returns null if no adjustment is 233 /// required. 234 llvm::Constant *CGCXXABI::getMemberPointerAdjustment(const CastExpr *E) { 235 assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || 236 E->getCastKind() == CK_BaseToDerivedMemberPointer); 237 238 QualType derivedType; 239 if (E->getCastKind() == CK_DerivedToBaseMemberPointer) 240 derivedType = E->getSubExpr()->getType(); 241 else 242 derivedType = E->getType(); 243 244 const CXXRecordDecl *derivedClass = 245 derivedType->castAs<MemberPointerType>()->getClass()->getAsCXXRecordDecl(); 246 247 return CGM.GetNonVirtualBaseClassOffset(derivedClass, 248 E->path_begin(), 249 E->path_end()); 250 } 251 252 CharUnits CGCXXABI::getMemberPointerPathAdjustment(const APValue &MP) { 253 // TODO: Store base specifiers in APValue member pointer paths so we can 254 // easily reuse CGM.GetNonVirtualBaseClassOffset(). 255 const ValueDecl *MPD = MP.getMemberPointerDecl(); 256 CharUnits ThisAdjustment = CharUnits::Zero(); 257 ArrayRef<const CXXRecordDecl*> Path = MP.getMemberPointerPath(); 258 bool DerivedMember = MP.isMemberPointerToDerivedMember(); 259 const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPD->getDeclContext()); 260 for (unsigned I = 0, N = Path.size(); I != N; ++I) { 261 const CXXRecordDecl *Base = RD; 262 const CXXRecordDecl *Derived = Path[I]; 263 if (DerivedMember) 264 std::swap(Base, Derived); 265 ThisAdjustment += 266 getContext().getASTRecordLayout(Derived).getBaseClassOffset(Base); 267 RD = Path[I]; 268 } 269 if (DerivedMember) 270 ThisAdjustment = -ThisAdjustment; 271 return ThisAdjustment; 272 } 273 274 llvm::BasicBlock * 275 CGCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, 276 const CXXRecordDecl *RD) { 277 if (CGM.getTarget().getCXXABI().hasConstructorVariants()) 278 llvm_unreachable("shouldn't be called in this ABI"); 279 280 ErrorUnsupportedABI(CGF, "complete object detection in ctor"); 281 return nullptr; 282 } 283 284 void CGCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV, 285 const CXXDestructorDecl *Dtor, 286 CXXDtorType DT) const { 287 // Assume the base C++ ABI has no special rules for destructor variants. 288 CGM.setDLLImportDLLExport(GV, Dtor); 289 } 290 291 llvm::GlobalValue::LinkageTypes CGCXXABI::getCXXDestructorLinkage( 292 GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const { 293 // Delegate back to CGM by default. 294 return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage, 295 /*IsConstantVariable=*/false); 296 } 297 298 bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) { 299 return false; 300 } 301 302 llvm::CallInst * 303 CGCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF, 304 llvm::Value *Exn) { 305 // Just call std::terminate and ignore the violating exception. 306 return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn()); 307 } 308 309 CatchTypeInfo CGCXXABI::getCatchAllTypeInfo() { 310 return CatchTypeInfo{nullptr, 0}; 311 } 312 313 std::vector<CharUnits> CGCXXABI::getVBPtrOffsets(const CXXRecordDecl *RD) { 314 return std::vector<CharUnits>(); 315 } 316