Path: blob/main/contrib/llvm-project/clang/lib/CodeGen/CGCXXABI.cpp
35233 views
//===----- CGCXXABI.cpp - Interface to C++ ABIs ---------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This provides an abstract class for C++ code generation. Concrete subclasses9// of this implement code generation for specific C++ ABIs.10//11//===----------------------------------------------------------------------===//1213#include "CGCXXABI.h"14#include "CGCleanup.h"15#include "clang/AST/Attr.h"1617using namespace clang;18using namespace CodeGen;1920CGCXXABI::~CGCXXABI() { }2122Address CGCXXABI::getThisAddress(CodeGenFunction &CGF) {23return CGF.makeNaturalAddressForPointer(24CGF.CXXABIThisValue, CGF.CXXABIThisDecl->getType()->getPointeeType(),25CGF.CXXABIThisAlignment);26}2728void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) {29DiagnosticsEngine &Diags = CGF.CGM.getDiags();30unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,31"cannot yet compile %0 in this ABI");32Diags.Report(CGF.getContext().getFullLoc(CGF.CurCodeDecl->getLocation()),33DiagID)34<< S;35}3637llvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) {38return llvm::Constant::getNullValue(CGM.getTypes().ConvertType(T));39}4041llvm::Type *42CGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {43return CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());44}4546CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer(47CodeGenFunction &CGF, const Expr *E, Address This,48llvm::Value *&ThisPtrForCall,49llvm::Value *MemPtr, const MemberPointerType *MPT) {50ErrorUnsupportedABI(CGF, "calls through member pointers");5152const auto *RD =53cast<CXXRecordDecl>(MPT->getClass()->castAs<RecordType>()->getDecl());54ThisPtrForCall =55CGF.getAsNaturalPointerTo(This, CGF.getContext().getRecordType(RD));56const FunctionProtoType *FPT =57MPT->getPointeeType()->getAs<FunctionProtoType>();58llvm::Constant *FnPtr = llvm::Constant::getNullValue(59llvm::PointerType::getUnqual(CGM.getLLVMContext()));60return CGCallee::forDirect(FnPtr, FPT);61}6263llvm::Value *64CGCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,65Address Base, llvm::Value *MemPtr,66const MemberPointerType *MPT) {67ErrorUnsupportedABI(CGF, "loads of member pointers");68llvm::Type *Ty =69llvm::PointerType::get(CGF.getLLVMContext(), Base.getAddressSpace());70return llvm::Constant::getNullValue(Ty);71}7273llvm::Value *CGCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,74const CastExpr *E,75llvm::Value *Src) {76ErrorUnsupportedABI(CGF, "member function pointer conversions");77return GetBogusMemberPointer(E->getType());78}7980llvm::Constant *CGCXXABI::EmitMemberPointerConversion(const CastExpr *E,81llvm::Constant *Src) {82return GetBogusMemberPointer(E->getType());83}8485llvm::Value *86CGCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,87llvm::Value *L,88llvm::Value *R,89const MemberPointerType *MPT,90bool Inequality) {91ErrorUnsupportedABI(CGF, "member function pointer comparison");92return CGF.Builder.getFalse();93}9495llvm::Value *96CGCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,97llvm::Value *MemPtr,98const MemberPointerType *MPT) {99ErrorUnsupportedABI(CGF, "member function pointer null testing");100return CGF.Builder.getFalse();101}102103llvm::Constant *104CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {105return GetBogusMemberPointer(QualType(MPT, 0));106}107108llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {109return GetBogusMemberPointer(CGM.getContext().getMemberPointerType(110MD->getType(), MD->getParent()->getTypeForDecl()));111}112113llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,114CharUnits offset) {115return GetBogusMemberPointer(QualType(MPT, 0));116}117118llvm::Constant *CGCXXABI::EmitMemberPointer(const APValue &MP, QualType MPT) {119return GetBogusMemberPointer(MPT);120}121122bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) {123// Fake answer.124return true;125}126127void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList ¶ms) {128const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());129130// FIXME: I'm not entirely sure I like using a fake decl just for code131// generation. Maybe we can come up with a better way?132auto *ThisDecl =133ImplicitParamDecl::Create(CGM.getContext(), nullptr, MD->getLocation(),134&CGM.getContext().Idents.get("this"),135MD->getThisType(), ImplicitParamKind::CXXThis);136params.push_back(ThisDecl);137CGF.CXXABIThisDecl = ThisDecl;138139// Compute the presumed alignment of 'this', which basically comes140// down to whether we know it's a complete object or not.141auto &Layout = CGF.getContext().getASTRecordLayout(MD->getParent());142if (MD->getParent()->getNumVBases() == 0 || // avoid vcall in common case143MD->getParent()->isEffectivelyFinal() ||144isThisCompleteObject(CGF.CurGD)) {145CGF.CXXABIThisAlignment = Layout.getAlignment();146} else {147CGF.CXXABIThisAlignment = Layout.getNonVirtualAlignment();148}149}150151llvm::Value *CGCXXABI::loadIncomingCXXThis(CodeGenFunction &CGF) {152return CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)),153"this");154}155156void CGCXXABI::setCXXABIThisValue(CodeGenFunction &CGF, llvm::Value *ThisPtr) {157/// Initialize the 'this' slot.158assert(getThisDecl(CGF) && "no 'this' variable for function");159CGF.CXXABIThisValue = ThisPtr;160}161162bool CGCXXABI::mayNeedDestruction(const VarDecl *VD) const {163if (VD->needsDestruction(getContext()))164return true;165166// If the variable has an incomplete class type (or array thereof), it167// might need destruction.168const Type *T = VD->getType()->getBaseElementTypeUnsafe();169if (T->getAs<RecordType>() && T->isIncompleteType())170return true;171172return false;173}174175bool CGCXXABI::isEmittedWithConstantInitializer(176const VarDecl *VD, bool InspectInitForWeakDef) const {177VD = VD->getMostRecentDecl();178if (VD->hasAttr<ConstInitAttr>())179return true;180181// All later checks examine the initializer specified on the variable. If182// the variable is weak, such examination would not be correct.183if (!InspectInitForWeakDef && (VD->isWeak() || VD->hasAttr<SelectAnyAttr>()))184return false;185186const VarDecl *InitDecl = VD->getInitializingDeclaration();187if (!InitDecl)188return false;189190// If there's no initializer to run, this is constant initialization.191if (!InitDecl->hasInit())192return true;193194// If we have the only definition, we don't need a thread wrapper if we195// will emit the value as a constant.196if (isUniqueGVALinkage(getContext().GetGVALinkageForVariable(VD)))197return !mayNeedDestruction(VD) && InitDecl->evaluateValue();198199// Otherwise, we need a thread wrapper unless we know that every200// translation unit will emit the value as a constant. We rely on the201// variable being constant-initialized in every translation unit if it's202// constant-initialized in any translation unit, which isn't actually203// guaranteed by the standard but is necessary for sanity.204return InitDecl->hasConstantInitialization();205}206207void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,208RValue RV, QualType ResultType) {209assert(!CGF.hasAggregateEvaluationKind(ResultType) &&210"cannot handle aggregates");211CGF.EmitReturnOfRValue(RV, ResultType);212}213214CharUnits CGCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) {215if (!requiresArrayCookie(expr))216return CharUnits::Zero();217return getArrayCookieSizeImpl(expr->getAllocatedType());218}219220CharUnits CGCXXABI::getArrayCookieSizeImpl(QualType elementType) {221// BOGUS222return CharUnits::Zero();223}224225Address CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,226Address NewPtr,227llvm::Value *NumElements,228const CXXNewExpr *expr,229QualType ElementType) {230// Should never be called.231ErrorUnsupportedABI(CGF, "array cookie initialization");232return Address::invalid();233}234235bool CGCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,236QualType elementType) {237// If the class's usual deallocation function takes two arguments,238// it needs a cookie.239if (expr->doesUsualArrayDeleteWantSize())240return true;241242return elementType.isDestructedType();243}244245bool CGCXXABI::requiresArrayCookie(const CXXNewExpr *expr) {246// If the class's usual deallocation function takes two arguments,247// it needs a cookie.248if (expr->doesUsualArrayDeleteWantSize())249return true;250251return expr->getAllocatedType().isDestructedType();252}253254void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr,255const CXXDeleteExpr *expr, QualType eltTy,256llvm::Value *&numElements,257llvm::Value *&allocPtr, CharUnits &cookieSize) {258// Derive a char* in the same address space as the pointer.259ptr = ptr.withElementType(CGF.Int8Ty);260261// If we don't need an array cookie, bail out early.262if (!requiresArrayCookie(expr, eltTy)) {263allocPtr = ptr.emitRawPointer(CGF);264numElements = nullptr;265cookieSize = CharUnits::Zero();266return;267}268269cookieSize = getArrayCookieSizeImpl(eltTy);270Address allocAddr = CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize);271allocPtr = allocAddr.emitRawPointer(CGF);272numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize);273}274275llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,276Address ptr,277CharUnits cookieSize) {278ErrorUnsupportedABI(CGF, "reading a new[] cookie");279return llvm::ConstantInt::get(CGF.SizeTy, 0);280}281282/// Returns the adjustment, in bytes, required for the given283/// member-pointer operation. Returns null if no adjustment is284/// required.285llvm::Constant *CGCXXABI::getMemberPointerAdjustment(const CastExpr *E) {286assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||287E->getCastKind() == CK_BaseToDerivedMemberPointer);288289QualType derivedType;290if (E->getCastKind() == CK_DerivedToBaseMemberPointer)291derivedType = E->getSubExpr()->getType();292else293derivedType = E->getType();294295const CXXRecordDecl *derivedClass =296derivedType->castAs<MemberPointerType>()->getClass()->getAsCXXRecordDecl();297298return CGM.GetNonVirtualBaseClassOffset(derivedClass,299E->path_begin(),300E->path_end());301}302303llvm::BasicBlock *304CGCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,305const CXXRecordDecl *RD) {306if (CGM.getTarget().getCXXABI().hasConstructorVariants())307llvm_unreachable("shouldn't be called in this ABI");308309ErrorUnsupportedABI(CGF, "complete object detection in ctor");310return nullptr;311}312313void CGCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV,314const CXXDestructorDecl *Dtor,315CXXDtorType DT) const {316// Assume the base C++ ABI has no special rules for destructor variants.317CGM.setDLLImportDLLExport(GV, Dtor);318}319320llvm::GlobalValue::LinkageTypes CGCXXABI::getCXXDestructorLinkage(321GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const {322// Delegate back to CGM by default.323return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage);324}325326bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) {327return false;328}329330llvm::CallInst *331CGCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,332llvm::Value *Exn) {333// Just call std::terminate and ignore the violating exception.334return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn());335}336337CatchTypeInfo CGCXXABI::getCatchAllTypeInfo() {338return CatchTypeInfo{nullptr, 0};339}340341std::vector<CharUnits> CGCXXABI::getVBPtrOffsets(const CXXRecordDecl *RD) {342return std::vector<CharUnits>();343}344345CGCXXABI::AddedStructorArgCounts CGCXXABI::addImplicitConstructorArgs(346CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type,347bool ForVirtualBase, bool Delegating, CallArgList &Args) {348AddedStructorArgs AddedArgs =349getImplicitConstructorArgs(CGF, D, Type, ForVirtualBase, Delegating);350for (size_t i = 0; i < AddedArgs.Prefix.size(); ++i) {351Args.insert(Args.begin() + 1 + i,352CallArg(RValue::get(AddedArgs.Prefix[i].Value),353AddedArgs.Prefix[i].Type));354}355for (const auto &arg : AddedArgs.Suffix) {356Args.add(RValue::get(arg.Value), arg.Type);357}358return AddedStructorArgCounts(AddedArgs.Prefix.size(),359AddedArgs.Suffix.size());360}361362363