brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.8 KiB · 57b1a1f Raw
345 lines · c
1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This provides an abstract class for C++ code generation. Concrete subclasses10// of this implement code generation for specific C++ ABIs.11//12//===----------------------------------------------------------------------===//13 14#ifndef LLVM_CLANG_LIB_CIR_CIRGENCXXABI_H15#define LLVM_CLANG_LIB_CIR_CIRGENCXXABI_H16 17#include "CIRGenCall.h"18#include "CIRGenCleanup.h"19#include "CIRGenFunction.h"20#include "CIRGenModule.h"21 22#include "clang/AST/Mangle.h"23 24namespace clang::CIRGen {25 26/// Implements C++ ABI-specific code generation functions.27class CIRGenCXXABI {28protected:29  CIRGenModule &cgm;30  std::unique_ptr<clang::MangleContext> mangleContext;31 32  virtual bool requiresArrayCookie(const CXXNewExpr *e);33 34public:35  // TODO(cir): make this protected when target-specific CIRGenCXXABIs are36  // implemented.37  CIRGenCXXABI(CIRGenModule &cgm)38      : cgm(cgm), mangleContext(cgm.getASTContext().createMangleContext()) {}39  virtual ~CIRGenCXXABI();40 41  void setCXXABIThisValue(CIRGenFunction &cgf, mlir::Value thisPtr);42 43  /// Emit the code to initialize hidden members required to handle virtual44  /// inheritance, if needed by the ABI.45  virtual void46  initializeHiddenVirtualInheritanceMembers(CIRGenFunction &cgf,47                                            const CXXRecordDecl *rd) {}48 49  /// Emit a single constructor/destructor with the gen type from a C++50  /// constructor/destructor Decl.51  virtual void emitCXXStructor(clang::GlobalDecl gd) = 0;52 53  virtual mlir::Value54  getVirtualBaseClassOffset(mlir::Location loc, CIRGenFunction &cgf,55                            Address thisAddr, const CXXRecordDecl *classDecl,56                            const CXXRecordDecl *baseClassDecl) = 0;57 58  virtual mlir::Value emitDynamicCast(CIRGenFunction &cgf, mlir::Location loc,59                                      QualType srcRecordTy,60                                      QualType destRecordTy,61                                      cir::PointerType destCIRTy,62                                      bool isRefCast, Address src) = 0;63 64public:65  /// Similar to AddedStructorArgs, but only notes the number of additional66  /// arguments.67  struct AddedStructorArgCounts {68    unsigned prefix = 0;69    unsigned suffix = 0;70    AddedStructorArgCounts() = default;71    AddedStructorArgCounts(unsigned p, unsigned s) : prefix(p), suffix(s) {}72    static AddedStructorArgCounts withPrefix(unsigned n) { return {n, 0}; }73    static AddedStructorArgCounts withSuffix(unsigned n) { return {0, n}; }74  };75 76  /// Additional implicit arguments to add to the beginning (Prefix) and end77  /// (Suffix) of a constructor / destructor arg list.78  ///79  /// Note that Prefix should actually be inserted *after* the first existing80  /// arg; `this` arguments always come first.81  struct AddedStructorArgs {82    struct Arg {83      mlir::Value value;84      QualType type;85    };86    llvm::SmallVector<Arg, 1> prefix;87    llvm::SmallVector<Arg, 1> suffix;88    AddedStructorArgs() = default;89    AddedStructorArgs(llvm::SmallVector<Arg, 1> p, llvm::SmallVector<Arg, 1> s)90        : prefix(std::move(p)), suffix(std::move(s)) {}91    static AddedStructorArgs withPrefix(llvm::SmallVector<Arg, 1> args) {92      return {std::move(args), {}};93    }94    static AddedStructorArgs withSuffix(llvm::SmallVector<Arg, 1> args) {95      return {{}, std::move(args)};96    }97  };98 99  /// Build the signature of the given constructor or destructor vairant by100  /// adding any required parameters. For convenience, ArgTys has been101  /// initialized with the type of 'this'.102  virtual AddedStructorArgCounts103  buildStructorSignature(GlobalDecl gd,104                         llvm::SmallVectorImpl<CanQualType> &argTys) = 0;105 106  AddedStructorArgCounts107  addImplicitConstructorArgs(CIRGenFunction &cgf, const CXXConstructorDecl *d,108                             CXXCtorType type, bool forVirtualBase,109                             bool delegating, CallArgList &args);110 111  clang::ImplicitParamDecl *getThisDecl(CIRGenFunction &cgf) {112    return cgf.cxxabiThisDecl;113  }114 115  virtual AddedStructorArgs116  getImplicitConstructorArgs(CIRGenFunction &cgf, const CXXConstructorDecl *d,117                             CXXCtorType type, bool forVirtualBase,118                             bool delegating) = 0;119 120  /// Emit the ABI-specific prolog for the function121  virtual void emitInstanceFunctionProlog(SourceLocation loc,122                                          CIRGenFunction &cgf) = 0;123 124  virtual void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) = 0;125  virtual void emitThrow(CIRGenFunction &cgf, const CXXThrowExpr *e) = 0;126 127  virtual void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc) = 0;128 129  virtual mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc,130                                                  QualType ty) = 0;131 132  /// Get the type of the implicit "this" parameter used by a method. May return133  /// zero if no specific type is applicable, e.g. if the ABI expects the "this"134  /// parameter to point to some artificial offset in a complete object due to135  /// vbases being reordered.136  virtual const clang::CXXRecordDecl *137  getThisArgumentTypeForMethod(const clang::CXXMethodDecl *md) {138    return md->getParent();139  }140 141  /// Return whether the given global decl needs a VTT (virtual table table)142  /// parameter.143  virtual bool needsVTTParameter(clang::GlobalDecl gd) { return false; }144 145  /// Perform ABI-specific "this" argument adjustment required prior to146  /// a call of a virtual function.147  /// The "VirtualCall" argument is true iff the call itself is virtual.148  virtual Address adjustThisArgumentForVirtualFunctionCall(CIRGenFunction &cgf,149                                                           clang::GlobalDecl gd,150                                                           Address thisPtr,151                                                           bool virtualCall) {152    return thisPtr;153  }154 155  /// Build a parameter variable suitable for 'this'.156  void buildThisParam(CIRGenFunction &cgf, FunctionArgList &params);157 158  /// Loads the incoming C++ this pointer as it was passed by the caller.159  mlir::Value loadIncomingCXXThis(CIRGenFunction &cgf);160 161  virtual CatchTypeInfo getCatchAllTypeInfo();162 163  /// Get the implicit (second) parameter that comes after the "this" pointer,164  /// or nullptr if there is isn't one.165  virtual mlir::Value getCXXDestructorImplicitParam(CIRGenFunction &cgf,166                                                    const CXXDestructorDecl *dd,167                                                    CXXDtorType type,168                                                    bool forVirtualBase,169                                                    bool delegating) = 0;170 171  /// Emit constructor variants required by this ABI.172  virtual void emitCXXConstructors(const clang::CXXConstructorDecl *d) = 0;173 174  /// Emit dtor variants required by this ABI.175  virtual void emitCXXDestructors(const clang::CXXDestructorDecl *d) = 0;176 177  virtual void emitDestructorCall(CIRGenFunction &cgf,178                                  const CXXDestructorDecl *dd, CXXDtorType type,179                                  bool forVirtualBase, bool delegating,180                                  Address thisAddr, QualType thisTy) = 0;181 182  /// Emit code to force the execution of a destructor during global183  /// teardown.  The default implementation of this uses atexit.184  ///185  /// \param dtor - a function taking a single pointer argument186  /// \param addr - a pointer to pass to the destructor function.187  virtual void registerGlobalDtor(const VarDecl *vd, cir::FuncOp dtor,188                                  mlir::Value addr) = 0;189 190  virtual void emitVirtualObjectDelete(CIRGenFunction &cgf,191                                       const CXXDeleteExpr *de, Address ptr,192                                       QualType elementType,193                                       const CXXDestructorDecl *dtor) = 0;194 195  virtual size_t getSrcArgforCopyCtor(const CXXConstructorDecl *,196                                      FunctionArgList &args) const = 0;197 198  /// Checks if ABI requires extra virtual offset for vtable field.199  virtual bool200  isVirtualOffsetNeededForVTableField(CIRGenFunction &cgf,201                                      CIRGenFunction::VPtr vptr) = 0;202 203  /// Emits the VTable definitions required for the given record type.204  virtual void emitVTableDefinitions(CIRGenVTables &cgvt,205                                     const CXXRecordDecl *rd) = 0;206 207  using DeleteOrMemberCallExpr =208      llvm::PointerUnion<const CXXDeleteExpr *, const CXXMemberCallExpr *>;209 210  virtual mlir::Value emitVirtualDestructorCall(CIRGenFunction &cgf,211                                                const CXXDestructorDecl *dtor,212                                                CXXDtorType dtorType,213                                                Address thisAddr,214                                                DeleteOrMemberCallExpr e) = 0;215 216  /// Emit any tables needed to implement virtual inheritance.  For Itanium,217  /// this emits virtual table tables.218  virtual void emitVirtualInheritanceTables(const CXXRecordDecl *rd) = 0;219 220  /// Returns true if the given destructor type should be emitted as a linkonce221  /// delegating thunk, regardless of whether the dtor is defined in this TU or222  /// not.223  virtual bool useThunkForDtorVariant(const CXXDestructorDecl *dtor,224                                      CXXDtorType dt) const = 0;225 226  virtual cir::GlobalLinkageKind227  getCXXDestructorLinkage(GVALinkage linkage, const CXXDestructorDecl *dtor,228                          CXXDtorType dt) const;229 230  /// Get the address of the vtable for the given record decl which should be231  /// used for the vptr at the given offset in RD.232  virtual cir::GlobalOp getAddrOfVTable(const CXXRecordDecl *rd,233                                        CharUnits vptrOffset) = 0;234 235  /// Build a virtual function pointer in the ABI-specific way.236  virtual CIRGenCallee getVirtualFunctionPointer(CIRGenFunction &cgf,237                                                 clang::GlobalDecl gd,238                                                 Address thisAddr,239                                                 mlir::Type ty,240                                                 SourceLocation loc) = 0;241 242  /// Get the address point of the vtable for the given base subobject.243  virtual mlir::Value244  getVTableAddressPoint(BaseSubobject base,245                        const CXXRecordDecl *vtableClass) = 0;246 247  /// Get the address point of the vtable for the given base subobject while248  /// building a constructor or a destructor.249  virtual mlir::Value getVTableAddressPointInStructor(250      CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base,251      const CXXRecordDecl *nearestVBase) = 0;252 253  /// Insert any ABI-specific implicit parameters into the parameter list for a254  /// function. This generally involves extra data for constructors and255  /// destructors.256  ///257  /// ABIs may also choose to override the return type, which has been258  /// initialized with the type of 'this' if HasThisReturn(CGF.CurGD) is true or259  /// the formal return type of the function otherwise.260  virtual void addImplicitStructorParams(CIRGenFunction &cgf,261                                         clang::QualType &resTy,262                                         FunctionArgList &params) = 0;263 264  /// Checks if ABI requires to initialize vptrs for given dynamic class.265  virtual bool266  doStructorsInitializeVPtrs(const clang::CXXRecordDecl *vtableClass) = 0;267 268  /// Returns true if the given constructor or destructor is one of the kinds269  /// that the ABI says returns 'this' (only applies when called non-virtually270  /// for destructors).271  ///272  /// There currently is no way to indicate if a destructor returns 'this' when273  /// called virtually, and CIR generation does not support this case.274  virtual bool hasThisReturn(clang::GlobalDecl gd) const { return false; }275 276  virtual bool hasMostDerivedReturn(clang::GlobalDecl gd) const {277    return false;278  }279 280  /// Returns true if the target allows calling a function through a pointer281  /// with a different signature than the actual function (or equivalently,282  /// bitcasting a function or function pointer to a different function type).283  /// In principle in the most general case this could depend on the target, the284  /// calling convention, and the actual types of the arguments and return285  /// value. Here it just means whether the signature mismatch could *ever* be286  /// allowed; in other words, does the target do strict checking of signatures287  /// for all calls.288  virtual bool canCallMismatchedFunctionType() const { return true; }289 290  /// Gets the mangle context.291  clang::MangleContext &getMangleContext() { return *mangleContext; }292 293  clang::ImplicitParamDecl *&getStructorImplicitParamDecl(CIRGenFunction &cgf) {294    return cgf.cxxStructorImplicitParamDecl;295  }296 297  mlir::Value getStructorImplicitParamValue(CIRGenFunction &cgf) {298    return cgf.cxxStructorImplicitParamValue;299  }300 301  void setStructorImplicitParamValue(CIRGenFunction &cgf, mlir::Value val) {302    cgf.cxxStructorImplicitParamValue = val;303  }304 305  /**************************** Array cookies ******************************/306 307  /// Returns the extra size required in order to store the array308  /// cookie for the given new-expression.  May return 0 to indicate that no309  /// array cookie is required.310  ///311  /// Several cases are filtered out before this method is called:312  ///   - non-array allocations never need a cookie313  ///   - calls to \::operator new(size_t, void*) never need a cookie314  ///315  /// \param e - the new-expression being allocated.316  virtual CharUnits getArrayCookieSize(const CXXNewExpr *e);317 318  /// Initialize the array cookie for the given allocation.319  ///320  /// \param newPtr - a char* which is the presumed-non-null321  ///   return value of the allocation function322  /// \param numElements - the computed number of elements,323  ///   potentially collapsed from the multidimensional array case;324  ///   always a size_t325  /// \param elementType - the base element allocated type,326  ///   i.e. the allocated type after stripping all array types327  virtual Address initializeArrayCookie(CIRGenFunction &cgf, Address newPtr,328                                        mlir::Value numElements,329                                        const CXXNewExpr *e,330                                        QualType elementType) = 0;331 332protected:333  /// Returns the extra size required in order to store the array334  /// cookie for the given type.  Assumes that an array cookie is335  /// required.336  virtual CharUnits getArrayCookieSizeImpl(QualType elementType) = 0;337};338 339/// Creates and Itanium-family ABI340CIRGenCXXABI *CreateCIRGenItaniumCXXABI(CIRGenModule &cgm);341 342} // namespace clang::CIRGen343 344#endif345