
This change adds support for calling virtual functions. This includes adding the cir.vtable.get_virtual_fn_addr operation to lookup the address of the function being called from an object's vtable.
157 lines
6.3 KiB
C++
157 lines
6.3 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 "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;
|
|
|
|
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 a single constructor/destructor with the gen type from a C++
|
|
/// constructor/destructor Decl.
|
|
virtual void emitCXXStructor(clang::GlobalDecl gd) = 0;
|
|
|
|
public:
|
|
clang::ImplicitParamDecl *getThisDecl(CIRGenFunction &cgf) {
|
|
return cgf.cxxabiThisDecl;
|
|
}
|
|
|
|
/// Emit the ABI-specific prolog for the function
|
|
virtual void emitInstanceFunctionProlog(SourceLocation Loc,
|
|
CIRGenFunction &cgf) = 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);
|
|
|
|
/// 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;
|
|
|
|
/// Checks if ABI requires extra virtual offset for vtable field.
|
|
virtual bool
|
|
isVirtualOffsetNeededForVTableField(CIRGenFunction &cgf,
|
|
CIRGenFunction::VPtr vptr) = 0;
|
|
|
|
/// 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;
|
|
|
|
/// 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;
|
|
}
|
|
|
|
/// Gets the mangle context.
|
|
clang::MangleContext &getMangleContext() { return *mangleContext; }
|
|
};
|
|
|
|
/// Creates and Itanium-family ABI
|
|
CIRGenCXXABI *CreateCIRGenItaniumCXXABI(CIRGenModule &cgm);
|
|
|
|
} // namespace clang::CIRGen
|
|
|
|
#endif
|