Home | History | Annotate | Line # | Download | only in CodeGen
      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 &params) {
    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()->isEffectivelyFinal() ||
    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 llvm::BasicBlock *
    255 CGCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
    256                                         const CXXRecordDecl *RD) {
    257   if (CGM.getTarget().getCXXABI().hasConstructorVariants())
    258     llvm_unreachable("shouldn't be called in this ABI");
    259 
    260   ErrorUnsupportedABI(CGF, "complete object detection in ctor");
    261   return nullptr;
    262 }
    263 
    264 void CGCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
    265                                           const CXXDestructorDecl *Dtor,
    266                                           CXXDtorType DT) const {
    267   // Assume the base C++ ABI has no special rules for destructor variants.
    268   CGM.setDLLImportDLLExport(GV, Dtor);
    269 }
    270 
    271 llvm::GlobalValue::LinkageTypes CGCXXABI::getCXXDestructorLinkage(
    272     GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const {
    273   // Delegate back to CGM by default.
    274   return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage,
    275                                          /*IsConstantVariable=*/false);
    276 }
    277 
    278 bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) {
    279   return false;
    280 }
    281 
    282 llvm::CallInst *
    283 CGCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
    284                                               llvm::Value *Exn) {
    285   // Just call std::terminate and ignore the violating exception.
    286   return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn());
    287 }
    288 
    289 CatchTypeInfo CGCXXABI::getCatchAllTypeInfo() {
    290   return CatchTypeInfo{nullptr, 0};
    291 }
    292 
    293 std::vector<CharUnits> CGCXXABI::getVBPtrOffsets(const CXXRecordDecl *RD) {
    294   return std::vector<CharUnits>();
    295 }
    296 
    297 CGCXXABI::AddedStructorArgCounts CGCXXABI::addImplicitConstructorArgs(
    298     CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type,
    299     bool ForVirtualBase, bool Delegating, CallArgList &Args) {
    300   AddedStructorArgs AddedArgs =
    301       getImplicitConstructorArgs(CGF, D, Type, ForVirtualBase, Delegating);
    302   for (size_t i = 0; i < AddedArgs.Prefix.size(); ++i) {
    303     Args.insert(Args.begin() + 1 + i,
    304                 CallArg(RValue::get(AddedArgs.Prefix[i].Value),
    305                         AddedArgs.Prefix[i].Type));
    306   }
    307   for (const auto &arg : AddedArgs.Suffix) {
    308     Args.add(RValue::get(arg.Value), arg.Type);
    309   }
    310   return AddedStructorArgCounts(AddedArgs.Prefix.size(),
    311                                 AddedArgs.Suffix.size());
    312 }
    313