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 assert(!CGF.hasAggregateEvaluationKind(ResultType) && 160 "cannot handle aggregates"); 161 CGF.EmitReturnOfRValue(RV, ResultType); 162 } 163 164 CharUnits CGCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { 165 if (!requiresArrayCookie(expr)) 166 return CharUnits::Zero(); 167 return getArrayCookieSizeImpl(expr->getAllocatedType()); 168 } 169 170 CharUnits CGCXXABI::getArrayCookieSizeImpl(QualType elementType) { 171 // BOGUS 172 return CharUnits::Zero(); 173 } 174 175 Address CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, 176 Address NewPtr, 177 llvm::Value *NumElements, 178 const CXXNewExpr *expr, 179 QualType ElementType) { 180 // Should never be called. 181 ErrorUnsupportedABI(CGF, "array cookie initialization"); 182 return Address::invalid(); 183 } 184 185 bool CGCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr, 186 QualType elementType) { 187 // If the class's usual deallocation function takes two arguments, 188 // it needs a cookie. 189 if (expr->doesUsualArrayDeleteWantSize()) 190 return true; 191 192 return elementType.isDestructedType(); 193 } 194 195 bool CGCXXABI::requiresArrayCookie(const CXXNewExpr *expr) { 196 // If the class's usual deallocation function takes two arguments, 197 // it needs a cookie. 198 if (expr->doesUsualArrayDeleteWantSize()) 199 return true; 200 201 return expr->getAllocatedType().isDestructedType(); 202 } 203 204 void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr, 205 const CXXDeleteExpr *expr, QualType eltTy, 206 llvm::Value *&numElements, 207 llvm::Value *&allocPtr, CharUnits &cookieSize) { 208 // Derive a char* in the same address space as the pointer. 209 ptr = CGF.Builder.CreateElementBitCast(ptr, CGF.Int8Ty); 210 211 // If we don't need an array cookie, bail out early. 212 if (!requiresArrayCookie(expr, eltTy)) { 213 allocPtr = ptr.getPointer(); 214 numElements = nullptr; 215 cookieSize = CharUnits::Zero(); 216 return; 217 } 218 219 cookieSize = getArrayCookieSizeImpl(eltTy); 220 Address allocAddr = 221 CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize); 222 allocPtr = allocAddr.getPointer(); 223 numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize); 224 } 225 226 llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, 227 Address ptr, 228 CharUnits cookieSize) { 229 ErrorUnsupportedABI(CGF, "reading a new[] cookie"); 230 return llvm::ConstantInt::get(CGF.SizeTy, 0); 231 } 232 233 /// Returns the adjustment, in bytes, required for the given 234 /// member-pointer operation. Returns null if no adjustment is 235 /// required. 236 llvm::Constant *CGCXXABI::getMemberPointerAdjustment(const CastExpr *E) { 237 assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || 238 E->getCastKind() == CK_BaseToDerivedMemberPointer); 239 240 QualType derivedType; 241 if (E->getCastKind() == CK_DerivedToBaseMemberPointer) 242 derivedType = E->getSubExpr()->getType(); 243 else 244 derivedType = E->getType(); 245 246 const CXXRecordDecl *derivedClass = 247 derivedType->castAs<MemberPointerType>()->getClass()->getAsCXXRecordDecl(); 248 249 return CGM.GetNonVirtualBaseClassOffset(derivedClass, 250 E->path_begin(), 251 E->path_end()); 252 } 253 254 CharUnits CGCXXABI::getMemberPointerPathAdjustment(const APValue &MP) { 255 // TODO: Store base specifiers in APValue member pointer paths so we can 256 // easily reuse CGM.GetNonVirtualBaseClassOffset(). 257 const ValueDecl *MPD = MP.getMemberPointerDecl(); 258 CharUnits ThisAdjustment = CharUnits::Zero(); 259 ArrayRef<const CXXRecordDecl*> Path = MP.getMemberPointerPath(); 260 bool DerivedMember = MP.isMemberPointerToDerivedMember(); 261 const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPD->getDeclContext()); 262 for (unsigned I = 0, N = Path.size(); I != N; ++I) { 263 const CXXRecordDecl *Base = RD; 264 const CXXRecordDecl *Derived = Path[I]; 265 if (DerivedMember) 266 std::swap(Base, Derived); 267 ThisAdjustment += 268 getContext().getASTRecordLayout(Derived).getBaseClassOffset(Base); 269 RD = Path[I]; 270 } 271 if (DerivedMember) 272 ThisAdjustment = -ThisAdjustment; 273 return ThisAdjustment; 274 } 275 276 llvm::BasicBlock * 277 CGCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, 278 const CXXRecordDecl *RD) { 279 if (CGM.getTarget().getCXXABI().hasConstructorVariants()) 280 llvm_unreachable("shouldn't be called in this ABI"); 281 282 ErrorUnsupportedABI(CGF, "complete object detection in ctor"); 283 return nullptr; 284 } 285 286 void CGCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV, 287 const CXXDestructorDecl *Dtor, 288 CXXDtorType DT) const { 289 // Assume the base C++ ABI has no special rules for destructor variants. 290 CGM.setDLLImportDLLExport(GV, Dtor); 291 } 292 293 llvm::GlobalValue::LinkageTypes CGCXXABI::getCXXDestructorLinkage( 294 GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const { 295 // Delegate back to CGM by default. 296 return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage, 297 /*IsConstantVariable=*/false); 298 } 299 300 bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) { 301 return false; 302 } 303 304 llvm::CallInst * 305 CGCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF, 306 llvm::Value *Exn) { 307 // Just call std::terminate and ignore the violating exception. 308 return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn()); 309 } 310 311 CatchTypeInfo CGCXXABI::getCatchAllTypeInfo() { 312 return CatchTypeInfo{nullptr, 0}; 313 } 314 315 std::vector<CharUnits> CGCXXABI::getVBPtrOffsets(const CXXRecordDecl *RD) { 316 return std::vector<CharUnits>(); 317 } 318 319 CGCXXABI::AddedStructorArgCounts CGCXXABI::addImplicitConstructorArgs( 320 CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type, 321 bool ForVirtualBase, bool Delegating, CallArgList &Args) { 322 AddedStructorArgs AddedArgs = 323 getImplicitConstructorArgs(CGF, D, Type, ForVirtualBase, Delegating); 324 for (size_t i = 0; i < AddedArgs.Prefix.size(); ++i) { 325 Args.insert(Args.begin() + 1 + i, 326 CallArg(RValue::get(AddedArgs.Prefix[i].Value), 327 AddedArgs.Prefix[i].Type)); 328 } 329 for (const auto &arg : AddedArgs.Suffix) { 330 Args.add(RValue::get(arg.Value), arg.Type); 331 } 332 return AddedStructorArgCounts(AddedArgs.Prefix.size(), 333 AddedArgs.Suffix.size()); 334 } 335