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 ¶ms);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 ¶ms) = 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