CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
397 lines
17 KiB
C++
397 lines
17 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This provides an abstract class for C++ code generation. Concrete subclasses
|
|
// of this implement code generation for specific C++ ABIs.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CLANG_LIB_CIR_CIRGENCXXABI_H
|
|
#define LLVM_CLANG_LIB_CIR_CIRGENCXXABI_H
|
|
|
|
#include "CIRGenCall.h"
|
|
#include "CIRGenCleanup.h"
|
|
#include "CIRGenFunction.h"
|
|
#include "CIRGenModule.h"
|
|
|
|
#include "clang/AST/Mangle.h"
|
|
|
|
namespace clang::CIRGen {
|
|
|
|
/// Implements C++ ABI-specific code generation functions.
|
|
class CIRGenCXXABI {
|
|
protected:
|
|
CIRGenModule &cgm;
|
|
std::unique_ptr<clang::MangleContext> mangleContext;
|
|
|
|
virtual bool requiresArrayCookie(const CXXNewExpr *e);
|
|
|
|
public:
|
|
// TODO(cir): make this protected when target-specific CIRGenCXXABIs are
|
|
// implemented.
|
|
CIRGenCXXABI(CIRGenModule &cgm)
|
|
: cgm(cgm), mangleContext(cgm.getASTContext().createMangleContext()) {}
|
|
virtual ~CIRGenCXXABI();
|
|
|
|
void setCXXABIThisValue(CIRGenFunction &cgf, mlir::Value thisPtr);
|
|
|
|
/// Emit the code to initialize hidden members required to handle virtual
|
|
/// inheritance, if needed by the ABI.
|
|
virtual void
|
|
initializeHiddenVirtualInheritanceMembers(CIRGenFunction &cgf,
|
|
const CXXRecordDecl *rd) {}
|
|
|
|
/// Emit a single constructor/destructor with the gen type from a C++
|
|
/// constructor/destructor Decl.
|
|
virtual void emitCXXStructor(clang::GlobalDecl gd) = 0;
|
|
|
|
virtual mlir::Value
|
|
getVirtualBaseClassOffset(mlir::Location loc, CIRGenFunction &cgf,
|
|
Address thisAddr, const CXXRecordDecl *classDecl,
|
|
const CXXRecordDecl *baseClassDecl) = 0;
|
|
|
|
virtual mlir::Value emitDynamicCast(CIRGenFunction &cgf, mlir::Location loc,
|
|
QualType srcRecordTy,
|
|
QualType destRecordTy,
|
|
cir::PointerType destCIRTy,
|
|
bool isRefCast, Address src) = 0;
|
|
|
|
virtual cir::MethodAttr buildVirtualMethodAttr(cir::MethodType methodTy,
|
|
const CXXMethodDecl *md) = 0;
|
|
|
|
public:
|
|
/// Similar to AddedStructorArgs, but only notes the number of additional
|
|
/// arguments.
|
|
struct AddedStructorArgCounts {
|
|
unsigned prefix = 0;
|
|
unsigned suffix = 0;
|
|
AddedStructorArgCounts() = default;
|
|
AddedStructorArgCounts(unsigned p, unsigned s) : prefix(p), suffix(s) {}
|
|
static AddedStructorArgCounts withPrefix(unsigned n) { return {n, 0}; }
|
|
static AddedStructorArgCounts withSuffix(unsigned n) { return {0, n}; }
|
|
};
|
|
|
|
/// Additional implicit arguments to add to the beginning (Prefix) and end
|
|
/// (Suffix) of a constructor / destructor arg list.
|
|
///
|
|
/// Note that Prefix should actually be inserted *after* the first existing
|
|
/// arg; `this` arguments always come first.
|
|
struct AddedStructorArgs {
|
|
struct Arg {
|
|
mlir::Value value;
|
|
QualType type;
|
|
};
|
|
llvm::SmallVector<Arg, 1> prefix;
|
|
llvm::SmallVector<Arg, 1> suffix;
|
|
AddedStructorArgs() = default;
|
|
AddedStructorArgs(llvm::SmallVector<Arg, 1> p, llvm::SmallVector<Arg, 1> s)
|
|
: prefix(std::move(p)), suffix(std::move(s)) {}
|
|
static AddedStructorArgs withPrefix(llvm::SmallVector<Arg, 1> args) {
|
|
return {std::move(args), {}};
|
|
}
|
|
static AddedStructorArgs withSuffix(llvm::SmallVector<Arg, 1> args) {
|
|
return {{}, std::move(args)};
|
|
}
|
|
};
|
|
|
|
/// Build the signature of the given constructor or destructor vairant by
|
|
/// adding any required parameters. For convenience, ArgTys has been
|
|
/// initialized with the type of 'this'.
|
|
virtual AddedStructorArgCounts
|
|
buildStructorSignature(GlobalDecl gd,
|
|
llvm::SmallVectorImpl<CanQualType> &argTys) = 0;
|
|
|
|
AddedStructorArgCounts
|
|
addImplicitConstructorArgs(CIRGenFunction &cgf, const CXXConstructorDecl *d,
|
|
CXXCtorType type, bool forVirtualBase,
|
|
bool delegating, CallArgList &args);
|
|
|
|
clang::ImplicitParamDecl *getThisDecl(CIRGenFunction &cgf) {
|
|
return cgf.cxxabiThisDecl;
|
|
}
|
|
|
|
virtual AddedStructorArgs
|
|
getImplicitConstructorArgs(CIRGenFunction &cgf, const CXXConstructorDecl *d,
|
|
CXXCtorType type, bool forVirtualBase,
|
|
bool delegating) = 0;
|
|
|
|
/// Emit the ABI-specific prolog for the function
|
|
virtual void emitInstanceFunctionProlog(SourceLocation loc,
|
|
CIRGenFunction &cgf) = 0;
|
|
|
|
virtual void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) = 0;
|
|
virtual void emitThrow(CIRGenFunction &cgf, const CXXThrowExpr *e) = 0;
|
|
|
|
/// Determine whether it's possible to emit a vtable for \p RD, even
|
|
/// though we do not know that the vtable has been marked as used by semantic
|
|
/// analysis.
|
|
virtual bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const = 0;
|
|
|
|
virtual void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc) = 0;
|
|
|
|
virtual mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc,
|
|
QualType ty) = 0;
|
|
|
|
/// Get the type of the implicit "this" parameter used by a method. May return
|
|
/// zero if no specific type is applicable, e.g. if the ABI expects the "this"
|
|
/// parameter to point to some artificial offset in a complete object due to
|
|
/// vbases being reordered.
|
|
virtual const clang::CXXRecordDecl *
|
|
getThisArgumentTypeForMethod(const clang::CXXMethodDecl *md) {
|
|
return md->getParent();
|
|
}
|
|
|
|
/// Return whether the given global decl needs a VTT (virtual table table)
|
|
/// parameter.
|
|
virtual bool needsVTTParameter(clang::GlobalDecl gd) { return false; }
|
|
|
|
/// Perform ABI-specific "this" argument adjustment required prior to
|
|
/// a call of a virtual function.
|
|
/// The "VirtualCall" argument is true iff the call itself is virtual.
|
|
virtual Address adjustThisArgumentForVirtualFunctionCall(CIRGenFunction &cgf,
|
|
clang::GlobalDecl gd,
|
|
Address thisPtr,
|
|
bool virtualCall) {
|
|
return thisPtr;
|
|
}
|
|
|
|
/// Build a parameter variable suitable for 'this'.
|
|
void buildThisParam(CIRGenFunction &cgf, FunctionArgList ¶ms);
|
|
|
|
/// Loads the incoming C++ this pointer as it was passed by the caller.
|
|
mlir::Value loadIncomingCXXThis(CIRGenFunction &cgf);
|
|
|
|
virtual CatchTypeInfo
|
|
getAddrOfCXXCatchHandlerType(mlir::Location loc, QualType ty,
|
|
QualType catchHandlerType) = 0;
|
|
virtual CatchTypeInfo getCatchAllTypeInfo();
|
|
virtual bool shouldTypeidBeNullChecked(QualType srcTy) = 0;
|
|
virtual mlir::Value emitTypeid(CIRGenFunction &cgf, QualType srcTy,
|
|
Address thisPtr, mlir::Type typeInfoPtrTy) = 0;
|
|
virtual void emitBadTypeidCall(CIRGenFunction &cgf, mlir::Location loc) = 0;
|
|
|
|
/// Get the implicit (second) parameter that comes after the "this" pointer,
|
|
/// or nullptr if there is isn't one.
|
|
virtual mlir::Value getCXXDestructorImplicitParam(CIRGenFunction &cgf,
|
|
const CXXDestructorDecl *dd,
|
|
CXXDtorType type,
|
|
bool forVirtualBase,
|
|
bool delegating) = 0;
|
|
|
|
/// Emit constructor variants required by this ABI.
|
|
virtual void emitCXXConstructors(const clang::CXXConstructorDecl *d) = 0;
|
|
|
|
/// Emit dtor variants required by this ABI.
|
|
virtual void emitCXXDestructors(const clang::CXXDestructorDecl *d) = 0;
|
|
|
|
virtual void emitDestructorCall(CIRGenFunction &cgf,
|
|
const CXXDestructorDecl *dd, CXXDtorType type,
|
|
bool forVirtualBase, bool delegating,
|
|
Address thisAddr, QualType thisTy) = 0;
|
|
|
|
/// Emit code to force the execution of a destructor during global
|
|
/// teardown. The default implementation of this uses atexit.
|
|
///
|
|
/// \param dtor - a function taking a single pointer argument
|
|
/// \param addr - a pointer to pass to the destructor function.
|
|
virtual void registerGlobalDtor(const VarDecl *vd, cir::FuncOp dtor,
|
|
mlir::Value addr) = 0;
|
|
|
|
virtual void emitVirtualObjectDelete(CIRGenFunction &cgf,
|
|
const CXXDeleteExpr *de, Address ptr,
|
|
QualType elementType,
|
|
const CXXDestructorDecl *dtor) = 0;
|
|
|
|
virtual size_t getSrcArgforCopyCtor(const CXXConstructorDecl *,
|
|
FunctionArgList &args) const = 0;
|
|
|
|
/// Checks if ABI requires extra virtual offset for vtable field.
|
|
virtual bool
|
|
isVirtualOffsetNeededForVTableField(CIRGenFunction &cgf,
|
|
CIRGenFunction::VPtr vptr) = 0;
|
|
|
|
/// Emits the VTable definitions required for the given record type.
|
|
virtual void emitVTableDefinitions(CIRGenVTables &cgvt,
|
|
const CXXRecordDecl *rd) = 0;
|
|
|
|
using DeleteOrMemberCallExpr =
|
|
llvm::PointerUnion<const CXXDeleteExpr *, const CXXMemberCallExpr *>;
|
|
|
|
virtual mlir::Value emitVirtualDestructorCall(CIRGenFunction &cgf,
|
|
const CXXDestructorDecl *dtor,
|
|
CXXDtorType dtorType,
|
|
Address thisAddr,
|
|
DeleteOrMemberCallExpr e) = 0;
|
|
|
|
/// Emit any tables needed to implement virtual inheritance. For Itanium,
|
|
/// this emits virtual table tables.
|
|
virtual void emitVirtualInheritanceTables(const CXXRecordDecl *rd) = 0;
|
|
|
|
/// Returns true if the thunk should be exported.
|
|
virtual bool exportThunk() = 0;
|
|
|
|
/// Set the linkage and visibility of a thunk function.
|
|
virtual void setThunkLinkage(cir::FuncOp thunk, bool forVTable, GlobalDecl gd,
|
|
bool returnAdjustment) = 0;
|
|
|
|
/// Perform adjustment on the 'this' pointer for a thunk.
|
|
/// Returns the adjusted 'this' pointer value.
|
|
virtual mlir::Value
|
|
performThisAdjustment(CIRGenFunction &cgf, Address thisAddr,
|
|
const CXXRecordDecl *unadjustedClass,
|
|
const ThunkInfo &ti) = 0;
|
|
|
|
/// Perform adjustment on a return pointer for a thunk (covariant returns).
|
|
/// Returns the adjusted return pointer value.
|
|
virtual mlir::Value
|
|
performReturnAdjustment(CIRGenFunction &cgf, Address ret,
|
|
const CXXRecordDecl *unadjustedClass,
|
|
const ReturnAdjustment &ra) = 0;
|
|
|
|
/// Adjust call arguments for a destructor thunk.
|
|
virtual void adjustCallArgsForDestructorThunk(CIRGenFunction &cgf,
|
|
GlobalDecl globalDecl,
|
|
CallArgList &callArgs) {}
|
|
|
|
/// Emit a return from a thunk.
|
|
virtual void emitReturnFromThunk(CIRGenFunction &cgf, RValue rv,
|
|
QualType resultType);
|
|
|
|
/// Returns true if the given destructor type should be emitted as a linkonce
|
|
/// delegating thunk, regardless of whether the dtor is defined in this TU or
|
|
/// not.
|
|
virtual bool useThunkForDtorVariant(const CXXDestructorDecl *dtor,
|
|
CXXDtorType dt) const = 0;
|
|
|
|
virtual cir::GlobalLinkageKind
|
|
getCXXDestructorLinkage(GVALinkage linkage, const CXXDestructorDecl *dtor,
|
|
CXXDtorType dt) const;
|
|
|
|
/// Get the address of the vtable for the given record decl which should be
|
|
/// used for the vptr at the given offset in RD.
|
|
virtual cir::GlobalOp getAddrOfVTable(const CXXRecordDecl *rd,
|
|
CharUnits vptrOffset) = 0;
|
|
|
|
/// Build a virtual function pointer in the ABI-specific way.
|
|
virtual CIRGenCallee getVirtualFunctionPointer(CIRGenFunction &cgf,
|
|
clang::GlobalDecl gd,
|
|
Address thisAddr,
|
|
mlir::Type ty,
|
|
SourceLocation loc) = 0;
|
|
|
|
/// Get the address point of the vtable for the given base subobject.
|
|
virtual mlir::Value
|
|
getVTableAddressPoint(BaseSubobject base,
|
|
const CXXRecordDecl *vtableClass) = 0;
|
|
|
|
/// Get the address point of the vtable for the given base subobject while
|
|
/// building a constructor or a destructor.
|
|
virtual mlir::Value getVTableAddressPointInStructor(
|
|
CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base,
|
|
const CXXRecordDecl *nearestVBase) = 0;
|
|
|
|
virtual llvm::StringRef getPureVirtualCallName() = 0;
|
|
virtual llvm::StringRef getDeletedVirtualCallName() = 0;
|
|
|
|
/// Insert any ABI-specific implicit parameters into the parameter list for a
|
|
/// function. This generally involves extra data for constructors and
|
|
/// destructors.
|
|
///
|
|
/// ABIs may also choose to override the return type, which has been
|
|
/// initialized with the type of 'this' if HasThisReturn(CGF.CurGD) is true or
|
|
/// the formal return type of the function otherwise.
|
|
virtual void addImplicitStructorParams(CIRGenFunction &cgf,
|
|
clang::QualType &resTy,
|
|
FunctionArgList ¶ms) = 0;
|
|
|
|
/// Checks if ABI requires to initialize vptrs for given dynamic class.
|
|
virtual bool
|
|
doStructorsInitializeVPtrs(const clang::CXXRecordDecl *vtableClass) = 0;
|
|
|
|
/// Returns true if the given constructor or destructor is one of the kinds
|
|
/// that the ABI says returns 'this' (only applies when called non-virtually
|
|
/// for destructors).
|
|
///
|
|
/// There currently is no way to indicate if a destructor returns 'this' when
|
|
/// called virtually, and CIR generation does not support this case.
|
|
virtual bool hasThisReturn(clang::GlobalDecl gd) const { return false; }
|
|
|
|
virtual bool hasMostDerivedReturn(clang::GlobalDecl gd) const {
|
|
return false;
|
|
}
|
|
|
|
/// Returns true if the target allows calling a function through a pointer
|
|
/// with a different signature than the actual function (or equivalently,
|
|
/// bitcasting a function or function pointer to a different function type).
|
|
/// In principle in the most general case this could depend on the target, the
|
|
/// calling convention, and the actual types of the arguments and return
|
|
/// value. Here it just means whether the signature mismatch could *ever* be
|
|
/// allowed; in other words, does the target do strict checking of signatures
|
|
/// for all calls.
|
|
virtual bool canCallMismatchedFunctionType() const { return true; }
|
|
|
|
/// Gets the mangle context.
|
|
clang::MangleContext &getMangleContext() { return *mangleContext; }
|
|
|
|
clang::ImplicitParamDecl *&getStructorImplicitParamDecl(CIRGenFunction &cgf) {
|
|
return cgf.cxxStructorImplicitParamDecl;
|
|
}
|
|
|
|
mlir::Value getStructorImplicitParamValue(CIRGenFunction &cgf) {
|
|
return cgf.cxxStructorImplicitParamValue;
|
|
}
|
|
|
|
void setStructorImplicitParamValue(CIRGenFunction &cgf, mlir::Value val) {
|
|
cgf.cxxStructorImplicitParamValue = val;
|
|
}
|
|
|
|
/**************************** Array cookies ******************************/
|
|
|
|
/// Returns the extra size required in order to store the array
|
|
/// cookie for the given new-expression. May return 0 to indicate that no
|
|
/// array cookie is required.
|
|
///
|
|
/// Several cases are filtered out before this method is called:
|
|
/// - non-array allocations never need a cookie
|
|
/// - calls to \::operator new(size_t, void*) never need a cookie
|
|
///
|
|
/// \param e - the new-expression being allocated.
|
|
virtual CharUnits getArrayCookieSize(const CXXNewExpr *e);
|
|
|
|
/// Initialize the array cookie for the given allocation.
|
|
///
|
|
/// \param newPtr - a char* which is the presumed-non-null
|
|
/// return value of the allocation function
|
|
/// \param numElements - the computed number of elements,
|
|
/// potentially collapsed from the multidimensional array case;
|
|
/// always a size_t
|
|
/// \param elementType - the base element allocated type,
|
|
/// i.e. the allocated type after stripping all array types
|
|
virtual Address initializeArrayCookie(CIRGenFunction &cgf, Address newPtr,
|
|
mlir::Value numElements,
|
|
const CXXNewExpr *e,
|
|
QualType elementType) = 0;
|
|
|
|
/// Return true if the given member pointer can be zero-initialized
|
|
/// (in the C++ sense).
|
|
virtual bool isZeroInitializable(const MemberPointerType *mpt) = 0;
|
|
|
|
protected:
|
|
/// Returns the extra size required in order to store the array
|
|
/// cookie for the given type. Assumes that an array cookie is
|
|
/// required.
|
|
virtual CharUnits getArrayCookieSizeImpl(QualType elementType) = 0;
|
|
};
|
|
|
|
/// Creates and Itanium-family ABI
|
|
CIRGenCXXABI *CreateCIRGenItaniumCXXABI(CIRGenModule &cgm);
|
|
|
|
} // namespace clang::CIRGen
|
|
|
|
#endif
|