//===--- CIRGenTypes.h - Type translation for CIR CodeGen -------*- 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 is the code that handles AST -> CIR type lowering. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENTYPES_H #define LLVM_CLANG_LIB_CODEGEN_CODEGENTYPES_H #include "ABIInfo.h" #include "CIRGenFunctionInfo.h" #include "CIRGenRecordLayout.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/Type.h" #include "clang/Basic/ABI.h" #include "clang/CIR/Dialect/IR/CIRTypes.h" #include "llvm/ADT/SmallPtrSet.h" namespace clang { class ASTContext; class FunctionType; class GlobalDecl; class QualType; class Type; } // namespace clang namespace mlir { class Type; } namespace clang::CIRGen { class CallArgList; class CIRGenBuilderTy; class CIRGenCXXABI; class CIRGenModule; /// This class organizes the cross-module state that is used while lowering /// AST types to CIR types. class CIRGenTypes { CIRGenModule &cgm; clang::ASTContext &astContext; CIRGenBuilderTy &builder; CIRGenCXXABI &theCXXABI; const ABIInfo &theABIInfo; /// Contains the CIR type for any converted RecordDecl. llvm::DenseMap> cirGenRecordLayouts; /// Contains the CIR type for any converted RecordDecl llvm::DenseMap recordDeclTypes; /// Hold memoized CIRGenFunctionInfo results llvm::FoldingSet functionInfos; /// This set keeps track of records that we're currently converting to a CIR /// type. For example, when converting: /// struct A { struct B { int x; } } when processing 'x', the 'A' and 'B' /// types will be in this set. llvm::SmallPtrSet recordsBeingLaidOut; llvm::SmallVector deferredRecords; /// Heper for convertType. mlir::Type convertFunctionTypeInternal(clang::QualType ft); public: CIRGenTypes(CIRGenModule &cgm); ~CIRGenTypes(); CIRGenBuilderTy &getBuilder() const { return builder; } CIRGenModule &getCGModule() const { return cgm; } /// Utility to check whether a function type can be converted to a CIR type /// (i.e. doesn't depend on an incomplete tag type). bool isFuncTypeConvertible(const clang::FunctionType *ft); bool isFuncParamTypeConvertible(clang::QualType type); /// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR /// qualification. clang::CanQualType deriveThisType(const clang::CXXRecordDecl *rd, const clang::CXXMethodDecl *md); /// This map of clang::Type to mlir::Type (which includes CIR type) is a /// cache of types that have already been processed. using TypeCacheTy = llvm::DenseMap; TypeCacheTy typeCache; mlir::MLIRContext &getMLIRContext() const; clang::ASTContext &getASTContext() const { return astContext; } bool isRecordLayoutComplete(const clang::Type *ty) const; bool noRecordsBeingLaidOut() const { return recordsBeingLaidOut.empty(); } bool isRecordBeingLaidOut(const clang::Type *ty) const { return recordsBeingLaidOut.count(ty); } const ABIInfo &getABIInfo() const { return theABIInfo; } /// Convert a Clang type into a mlir::Type. mlir::Type convertType(clang::QualType type); mlir::Type convertRecordDeclType(const clang::RecordDecl *recordDecl); std::unique_ptr computeRecordLayout(const clang::RecordDecl *rd, cir::RecordType *ty); std::string getRecordTypeName(const clang::RecordDecl *, llvm::StringRef suffix); const CIRGenRecordLayout &getCIRGenRecordLayout(const clang::RecordDecl *rd); /// Convert type T into an mlir::Type. This differs from convertType in that /// it is used to convert to the memory representation for a type. For /// example, the scalar representation for bool is i1, but the memory /// representation is usually i8 or i32, depending on the target. // TODO: convert this comment to account for MLIR's equivalence mlir::Type convertTypeForMem(clang::QualType, bool forBitField = false); /// Get the CIR function type for \arg Info. cir::FuncType getFunctionType(const CIRGenFunctionInfo &info); cir::FuncType getFunctionType(clang::GlobalDecl gd); /// Get the CIR function type for use in a vtable, given a CXXMethodDecl. If /// the method has an incomplete return type, and/or incomplete argument /// types, this will return the opaque type. cir::FuncType getFunctionTypeForVTable(clang::GlobalDecl gd); // The arrangement methods are split into three families: // - those meant to drive the signature and prologue/epilogue // of a function declaration or definition, // - those meant for the computation of the CIR type for an abstract // appearance of a function, and // - those meant for performing the CIR-generation of a call. // They differ mainly in how they deal with optional (i.e. variadic) // arguments, as well as unprototyped functions. // // Key points: // - The CIRGenFunctionInfo for emitting a specific call site must include // entries for the optional arguments. // - The function type used at the call site must reflect the formal // signature // of the declaration being called, or else the call will go away. // - For the most part, unprototyped functions are called by casting to a // formal signature inferred from the specific argument types used at the // call-site. However, some targets (e.g. x86-64) screw with this for // compatability reasons. const CIRGenFunctionInfo &arrangeGlobalDeclaration(GlobalDecl gd); /// UpdateCompletedType - when we find the full definition for a TagDecl, /// replace the 'opaque' type we previously made for it if applicable. void updateCompletedType(const clang::TagDecl *td); /// Free functions are functions that are compatible with an ordinary C /// function pointer type. const CIRGenFunctionInfo & arrangeFunctionDeclaration(const clang::FunctionDecl *fd); /// Return whether a type can be zero-initialized (in the C++ sense) with an /// LLVM zeroinitializer. bool isZeroInitializable(clang::QualType ty); bool isZeroInitializable(const RecordDecl *rd); const CIRGenFunctionInfo &arrangeCXXConstructorCall( const CallArgList &args, const clang::CXXConstructorDecl *d, clang::CXXCtorType ctorKind, unsigned extraPrefixArgs, unsigned extraSuffixArgs, bool passProtoArgs = true); const CIRGenFunctionInfo & arrangeCXXMethodCall(const CallArgList &args, const clang::FunctionProtoType *type, RequiredArgs required, unsigned numPrefixArgs); /// C++ methods have some special rules and also have implicit parameters. const CIRGenFunctionInfo & arrangeCXXMethodDeclaration(const clang::CXXMethodDecl *md); const CIRGenFunctionInfo &arrangeCXXStructorDeclaration(clang::GlobalDecl gd); const CIRGenFunctionInfo & arrangeCXXMethodType(const clang::CXXRecordDecl *rd, const clang::FunctionProtoType *ftp, const clang::CXXMethodDecl *md); const CIRGenFunctionInfo &arrangeFreeFunctionCall(const CallArgList &args, const FunctionType *fnType); const CIRGenFunctionInfo & arrangeCIRFunctionInfo(CanQualType returnType, llvm::ArrayRef argTypes, RequiredArgs required); const CIRGenFunctionInfo & arrangeFreeFunctionType(CanQual fpt); const CIRGenFunctionInfo & arrangeFreeFunctionType(CanQual fnpt); }; } // namespace clang::CIRGen #endif