| 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 | Address CGCXXABI::getThisAddress(CodeGenFunction &CGF) { |
| 24 | return CGF.makeNaturalAddressForPointer( |
| 25 | Ptr: CGF.CXXABIThisValue, T: CGF.CXXABIThisDecl->getType()->getPointeeType(), |
| 26 | Alignment: CGF.CXXABIThisAlignment); |
| 27 | } |
| 28 | |
| 29 | void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) { |
| 30 | DiagnosticsEngine &Diags = CGF.CGM.getDiags(); |
| 31 | unsigned DiagID = Diags.getCustomDiagID(L: DiagnosticsEngine::Error, |
| 32 | FormatString: "cannot yet compile %0 in this ABI" ); |
| 33 | Diags.Report(Loc: CGF.getContext().getFullLoc(Loc: CGF.CurCodeDecl->getLocation()), |
| 34 | DiagID) |
| 35 | << S; |
| 36 | } |
| 37 | |
| 38 | llvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) { |
| 39 | return llvm::Constant::getNullValue(Ty: CGM.getTypes().ConvertType(T)); |
| 40 | } |
| 41 | |
| 42 | llvm::Type * |
| 43 | CGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) { |
| 44 | return CGM.getTypes().ConvertType(T: CGM.getContext().getPointerDiffType()); |
| 45 | } |
| 46 | |
| 47 | CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer( |
| 48 | CodeGenFunction &CGF, const Expr *E, Address This, |
| 49 | llvm::Value *&ThisPtrForCall, |
| 50 | llvm::Value *MemPtr, const MemberPointerType *MPT) { |
| 51 | ErrorUnsupportedABI(CGF, S: "calls through member pointers" ); |
| 52 | |
| 53 | const auto *RD = MPT->getMostRecentCXXRecordDecl(); |
| 54 | ThisPtrForCall = |
| 55 | CGF.getAsNaturalPointerTo(Addr: This, PointeeType: CGF.getContext().getRecordType(Decl: RD)); |
| 56 | const FunctionProtoType *FPT = |
| 57 | MPT->getPointeeType()->getAs<FunctionProtoType>(); |
| 58 | llvm::Constant *FnPtr = llvm::Constant::getNullValue( |
| 59 | Ty: llvm::PointerType::getUnqual(C&: CGM.getLLVMContext())); |
| 60 | return CGCallee::forDirect(functionPtr: FnPtr, abstractInfo: FPT); |
| 61 | } |
| 62 | |
| 63 | llvm::Value *CGCXXABI::EmitMemberDataPointerAddress( |
| 64 | CodeGenFunction &CGF, const Expr *E, Address Base, llvm::Value *MemPtr, |
| 65 | const MemberPointerType *MPT, bool IsInBounds) { |
| 66 | ErrorUnsupportedABI(CGF, S: "loads of member pointers" ); |
| 67 | llvm::Type *Ty = |
| 68 | llvm::PointerType::get(C&: CGF.getLLVMContext(), AddressSpace: Base.getAddressSpace()); |
| 69 | return llvm::Constant::getNullValue(Ty); |
| 70 | } |
| 71 | |
| 72 | llvm::Value *CGCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, |
| 73 | const CastExpr *E, |
| 74 | llvm::Value *Src) { |
| 75 | ErrorUnsupportedABI(CGF, S: "member function pointer conversions" ); |
| 76 | return GetBogusMemberPointer(T: E->getType()); |
| 77 | } |
| 78 | |
| 79 | llvm::Constant *CGCXXABI::EmitMemberPointerConversion(const CastExpr *E, |
| 80 | llvm::Constant *Src) { |
| 81 | return GetBogusMemberPointer(T: E->getType()); |
| 82 | } |
| 83 | |
| 84 | llvm::Value * |
| 85 | CGCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF, |
| 86 | llvm::Value *L, |
| 87 | llvm::Value *R, |
| 88 | const MemberPointerType *MPT, |
| 89 | bool Inequality) { |
| 90 | ErrorUnsupportedABI(CGF, S: "member function pointer comparison" ); |
| 91 | return CGF.Builder.getFalse(); |
| 92 | } |
| 93 | |
| 94 | llvm::Value * |
| 95 | CGCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF, |
| 96 | llvm::Value *MemPtr, |
| 97 | const MemberPointerType *MPT) { |
| 98 | ErrorUnsupportedABI(CGF, S: "member function pointer null testing" ); |
| 99 | return CGF.Builder.getFalse(); |
| 100 | } |
| 101 | |
| 102 | llvm::Constant * |
| 103 | CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { |
| 104 | return GetBogusMemberPointer(T: QualType(MPT, 0)); |
| 105 | } |
| 106 | |
| 107 | llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { |
| 108 | return GetBogusMemberPointer(T: CGM.getContext().getMemberPointerType( |
| 109 | T: MD->getType(), /*Qualifier=*/nullptr, Cls: MD->getParent())); |
| 110 | } |
| 111 | |
| 112 | llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, |
| 113 | CharUnits offset) { |
| 114 | return GetBogusMemberPointer(T: QualType(MPT, 0)); |
| 115 | } |
| 116 | |
| 117 | llvm::Constant *CGCXXABI::EmitMemberPointer(const APValue &MP, QualType MPT) { |
| 118 | return GetBogusMemberPointer(T: MPT); |
| 119 | } |
| 120 | |
| 121 | bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) { |
| 122 | // Fake answer. |
| 123 | return true; |
| 124 | } |
| 125 | |
| 126 | void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList ¶ms) { |
| 127 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(Val: CGF.CurGD.getDecl()); |
| 128 | |
| 129 | // FIXME: I'm not entirely sure I like using a fake decl just for code |
| 130 | // generation. Maybe we can come up with a better way? |
| 131 | auto *ThisDecl = |
| 132 | ImplicitParamDecl::Create(C&: CGM.getContext(), DC: nullptr, IdLoc: MD->getLocation(), |
| 133 | Id: &CGM.getContext().Idents.get(Name: "this" ), |
| 134 | T: MD->getThisType(), ParamKind: ImplicitParamKind::CXXThis); |
| 135 | params.push_back(Elt: ThisDecl); |
| 136 | CGF.CXXABIThisDecl = ThisDecl; |
| 137 | |
| 138 | // Compute the presumed alignment of 'this', which basically comes |
| 139 | // down to whether we know it's a complete object or not. |
| 140 | auto &Layout = CGF.getContext().getASTRecordLayout(D: MD->getParent()); |
| 141 | if (MD->getParent()->getNumVBases() == 0 || // avoid vcall in common case |
| 142 | MD->getParent()->isEffectivelyFinal() || |
| 143 | isThisCompleteObject(GD: CGF.CurGD)) { |
| 144 | CGF.CXXABIThisAlignment = Layout.getAlignment(); |
| 145 | } else { |
| 146 | CGF.CXXABIThisAlignment = Layout.getNonVirtualAlignment(); |
| 147 | } |
| 148 | } |
| 149 | |
| 150 | llvm::Value *CGCXXABI::loadIncomingCXXThis(CodeGenFunction &CGF) { |
| 151 | return CGF.Builder.CreateLoad(Addr: CGF.GetAddrOfLocalVar(VD: getThisDecl(CGF)), |
| 152 | Name: "this" ); |
| 153 | } |
| 154 | |
| 155 | void CGCXXABI::setCXXABIThisValue(CodeGenFunction &CGF, llvm::Value *ThisPtr) { |
| 156 | /// Initialize the 'this' slot. |
| 157 | assert(getThisDecl(CGF) && "no 'this' variable for function" ); |
| 158 | CGF.CXXABIThisValue = ThisPtr; |
| 159 | } |
| 160 | |
| 161 | bool CGCXXABI::mayNeedDestruction(const VarDecl *VD) const { |
| 162 | if (VD->needsDestruction(Ctx: getContext())) |
| 163 | return true; |
| 164 | |
| 165 | // If the variable has an incomplete class type (or array thereof), it |
| 166 | // might need destruction. |
| 167 | const Type *T = VD->getType()->getBaseElementTypeUnsafe(); |
| 168 | if (T->getAs<RecordType>() && T->isIncompleteType()) |
| 169 | return true; |
| 170 | |
| 171 | return false; |
| 172 | } |
| 173 | |
| 174 | bool CGCXXABI::isEmittedWithConstantInitializer( |
| 175 | const VarDecl *VD, bool InspectInitForWeakDef) const { |
| 176 | VD = VD->getMostRecentDecl(); |
| 177 | if (VD->hasAttr<ConstInitAttr>()) |
| 178 | return true; |
| 179 | |
| 180 | // All later checks examine the initializer specified on the variable. If |
| 181 | // the variable is weak, such examination would not be correct. |
| 182 | if (!InspectInitForWeakDef && (VD->isWeak() || VD->hasAttr<SelectAnyAttr>())) |
| 183 | return false; |
| 184 | |
| 185 | const VarDecl *InitDecl = VD->getInitializingDeclaration(); |
| 186 | if (!InitDecl) |
| 187 | return false; |
| 188 | |
| 189 | // If there's no initializer to run, this is constant initialization. |
| 190 | if (!InitDecl->hasInit()) |
| 191 | return true; |
| 192 | |
| 193 | // If we have the only definition, we don't need a thread wrapper if we |
| 194 | // will emit the value as a constant. |
| 195 | if (isUniqueGVALinkage(L: getContext().GetGVALinkageForVariable(VD))) |
| 196 | return !mayNeedDestruction(VD) && InitDecl->evaluateValue(); |
| 197 | |
| 198 | // Otherwise, we need a thread wrapper unless we know that every |
| 199 | // translation unit will emit the value as a constant. We rely on the |
| 200 | // variable being constant-initialized in every translation unit if it's |
| 201 | // constant-initialized in any translation unit, which isn't actually |
| 202 | // guaranteed by the standard but is necessary for sanity. |
| 203 | return InitDecl->hasConstantInitialization(); |
| 204 | } |
| 205 | |
| 206 | void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, |
| 207 | RValue RV, QualType ResultType) { |
| 208 | assert(!CGF.hasAggregateEvaluationKind(ResultType) && |
| 209 | "cannot handle aggregates" ); |
| 210 | CGF.EmitReturnOfRValue(RV, Ty: ResultType); |
| 211 | } |
| 212 | |
| 213 | CharUnits CGCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { |
| 214 | if (!requiresArrayCookie(E: expr)) |
| 215 | return CharUnits::Zero(); |
| 216 | return getArrayCookieSizeImpl(elementType: expr->getAllocatedType()); |
| 217 | } |
| 218 | |
| 219 | CharUnits CGCXXABI::getArrayCookieSizeImpl(QualType elementType) { |
| 220 | // BOGUS |
| 221 | return CharUnits::Zero(); |
| 222 | } |
| 223 | |
| 224 | Address CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, |
| 225 | Address NewPtr, |
| 226 | llvm::Value *NumElements, |
| 227 | const CXXNewExpr *expr, |
| 228 | QualType ElementType) { |
| 229 | // Should never be called. |
| 230 | ErrorUnsupportedABI(CGF, S: "array cookie initialization" ); |
| 231 | return Address::invalid(); |
| 232 | } |
| 233 | |
| 234 | bool CGCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr, |
| 235 | QualType elementType) { |
| 236 | // If the class's usual deallocation function takes two arguments, |
| 237 | // it needs a cookie. |
| 238 | if (expr->doesUsualArrayDeleteWantSize()) |
| 239 | return true; |
| 240 | |
| 241 | return elementType.isDestructedType(); |
| 242 | } |
| 243 | |
| 244 | bool CGCXXABI::requiresArrayCookie(const CXXNewExpr *expr) { |
| 245 | // If the class's usual deallocation function takes two arguments, |
| 246 | // it needs a cookie. |
| 247 | if (expr->doesUsualArrayDeleteWantSize()) |
| 248 | return true; |
| 249 | |
| 250 | return expr->getAllocatedType().isDestructedType(); |
| 251 | } |
| 252 | |
| 253 | void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr, |
| 254 | const CXXDeleteExpr *expr, QualType eltTy, |
| 255 | llvm::Value *&numElements, |
| 256 | llvm::Value *&allocPtr, CharUnits &cookieSize) { |
| 257 | // Derive a char* in the same address space as the pointer. |
| 258 | ptr = ptr.withElementType(ElemTy: CGF.Int8Ty); |
| 259 | |
| 260 | // If we don't need an array cookie, bail out early. |
| 261 | if (!requiresArrayCookie(expr, elementType: eltTy)) { |
| 262 | allocPtr = ptr.emitRawPointer(CGF); |
| 263 | numElements = nullptr; |
| 264 | cookieSize = CharUnits::Zero(); |
| 265 | return; |
| 266 | } |
| 267 | |
| 268 | cookieSize = getArrayCookieSizeImpl(elementType: eltTy); |
| 269 | Address allocAddr = CGF.Builder.CreateConstInBoundsByteGEP(Addr: ptr, Offset: -cookieSize); |
| 270 | allocPtr = allocAddr.emitRawPointer(CGF); |
| 271 | numElements = readArrayCookieImpl(IGF&: CGF, ptr: allocAddr, cookieSize); |
| 272 | } |
| 273 | |
| 274 | llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, |
| 275 | Address ptr, |
| 276 | CharUnits cookieSize) { |
| 277 | ErrorUnsupportedABI(CGF, S: "reading a new[] cookie" ); |
| 278 | return llvm::ConstantInt::get(Ty: CGF.SizeTy, V: 0); |
| 279 | } |
| 280 | |
| 281 | /// Returns the adjustment, in bytes, required for the given |
| 282 | /// member-pointer operation. Returns null if no adjustment is |
| 283 | /// required. |
| 284 | llvm::Constant *CGCXXABI::getMemberPointerAdjustment(const CastExpr *E) { |
| 285 | assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || |
| 286 | E->getCastKind() == CK_BaseToDerivedMemberPointer); |
| 287 | |
| 288 | QualType derivedType; |
| 289 | if (E->getCastKind() == CK_DerivedToBaseMemberPointer) |
| 290 | derivedType = E->getSubExpr()->getType(); |
| 291 | else |
| 292 | derivedType = E->getType(); |
| 293 | |
| 294 | const CXXRecordDecl *derivedClass = |
| 295 | derivedType->castAs<MemberPointerType>()->getMostRecentCXXRecordDecl(); |
| 296 | |
| 297 | return CGM.GetNonVirtualBaseClassOffset(ClassDecl: derivedClass, |
| 298 | PathBegin: E->path_begin(), |
| 299 | PathEnd: E->path_end()); |
| 300 | } |
| 301 | |
| 302 | llvm::BasicBlock * |
| 303 | CGCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, |
| 304 | const CXXRecordDecl *RD) { |
| 305 | if (CGM.getTarget().getCXXABI().hasConstructorVariants()) |
| 306 | llvm_unreachable("shouldn't be called in this ABI" ); |
| 307 | |
| 308 | ErrorUnsupportedABI(CGF, S: "complete object detection in ctor" ); |
| 309 | return nullptr; |
| 310 | } |
| 311 | |
| 312 | void CGCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV, |
| 313 | const CXXDestructorDecl *Dtor, |
| 314 | CXXDtorType DT) const { |
| 315 | // Assume the base C++ ABI has no special rules for destructor variants. |
| 316 | CGM.setDLLImportDLLExport(GV, D: Dtor); |
| 317 | } |
| 318 | |
| 319 | llvm::GlobalValue::LinkageTypes CGCXXABI::getCXXDestructorLinkage( |
| 320 | GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const { |
| 321 | // Delegate back to CGM by default. |
| 322 | return CGM.getLLVMLinkageForDeclarator(D: Dtor, Linkage); |
| 323 | } |
| 324 | |
| 325 | bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) { |
| 326 | return false; |
| 327 | } |
| 328 | |
| 329 | llvm::CallInst * |
| 330 | CGCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF, |
| 331 | llvm::Value *Exn) { |
| 332 | // Just call std::terminate and ignore the violating exception. |
| 333 | return CGF.EmitNounwindRuntimeCall(callee: CGF.CGM.getTerminateFn()); |
| 334 | } |
| 335 | |
| 336 | CatchTypeInfo CGCXXABI::getCatchAllTypeInfo() { |
| 337 | return CatchTypeInfo{.RTTI: nullptr, .Flags: 0}; |
| 338 | } |
| 339 | |
| 340 | std::vector<CharUnits> CGCXXABI::getVBPtrOffsets(const CXXRecordDecl *RD) { |
| 341 | return std::vector<CharUnits>(); |
| 342 | } |
| 343 | |
| 344 | CGCXXABI::AddedStructorArgCounts CGCXXABI::addImplicitConstructorArgs( |
| 345 | CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type, |
| 346 | bool ForVirtualBase, bool Delegating, CallArgList &Args) { |
| 347 | AddedStructorArgs AddedArgs = |
| 348 | getImplicitConstructorArgs(CGF, D, Type, ForVirtualBase, Delegating); |
| 349 | for (size_t i = 0; i < AddedArgs.Prefix.size(); ++i) { |
| 350 | Args.insert(I: Args.begin() + 1 + i, |
| 351 | Elt: CallArg(RValue::get(V: AddedArgs.Prefix[i].Value), |
| 352 | AddedArgs.Prefix[i].Type)); |
| 353 | } |
| 354 | for (const auto &arg : AddedArgs.Suffix) { |
| 355 | Args.add(rvalue: RValue::get(V: arg.Value), type: arg.Type); |
| 356 | } |
| 357 | return AddedStructorArgCounts(AddedArgs.Prefix.size(), |
| 358 | AddedArgs.Suffix.size()); |
| 359 | } |
| 360 | |