| 1 | //===--- CIRGenTypes.h - Type translation for CIR CodeGen -------*- C++ -*-===// |
| 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-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // This is the code that handles AST -> CIR type lowering. |
| 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | #ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENTYPES_H |
| 14 | #define LLVM_CLANG_LIB_CODEGEN_CODEGENTYPES_H |
| 15 | |
| 16 | #include "ABIInfo.h" |
| 17 | #include "CIRGenFunctionInfo.h" |
| 18 | #include "CIRGenRecordLayout.h" |
| 19 | |
| 20 | #include "clang/AST/DeclCXX.h" |
| 21 | #include "clang/AST/Type.h" |
| 22 | #include "clang/Basic/ABI.h" |
| 23 | #include "clang/CIR/Dialect/IR/CIRTypes.h" |
| 24 | |
| 25 | #include "llvm/ADT/SmallPtrSet.h" |
| 26 | |
| 27 | namespace clang { |
| 28 | class ASTContext; |
| 29 | class FunctionType; |
| 30 | class GlobalDecl; |
| 31 | class QualType; |
| 32 | class Type; |
| 33 | } // namespace clang |
| 34 | |
| 35 | namespace mlir { |
| 36 | class Type; |
| 37 | } |
| 38 | |
| 39 | namespace clang::CIRGen { |
| 40 | |
| 41 | class CallArgList; |
| 42 | class CIRGenBuilderTy; |
| 43 | class CIRGenCXXABI; |
| 44 | class CIRGenModule; |
| 45 | |
| 46 | /// This class organizes the cross-module state that is used while lowering |
| 47 | /// AST types to CIR types. |
| 48 | class CIRGenTypes { |
| 49 | CIRGenModule &cgm; |
| 50 | clang::ASTContext &astContext; |
| 51 | CIRGenBuilderTy &builder; |
| 52 | CIRGenCXXABI &theCXXABI; |
| 53 | |
| 54 | const ABIInfo &theABIInfo; |
| 55 | |
| 56 | /// Contains the CIR type for any converted RecordDecl. |
| 57 | llvm::DenseMap<const clang::Type *, std::unique_ptr<CIRGenRecordLayout>> |
| 58 | cirGenRecordLayouts; |
| 59 | |
| 60 | /// Contains the CIR type for any converted RecordDecl |
| 61 | llvm::DenseMap<const clang::Type *, cir::RecordType> recordDeclTypes; |
| 62 | |
| 63 | /// Hold memoized CIRGenFunctionInfo results |
| 64 | llvm::FoldingSet<CIRGenFunctionInfo> functionInfos; |
| 65 | |
| 66 | /// This set keeps track of records that we're currently converting to a CIR |
| 67 | /// type. For example, when converting: |
| 68 | /// struct A { struct B { int x; } } when processing 'x', the 'A' and 'B' |
| 69 | /// types will be in this set. |
| 70 | llvm::SmallPtrSet<const clang::Type *, 4> recordsBeingLaidOut; |
| 71 | |
| 72 | llvm::SmallVector<const clang::RecordDecl *, 8> deferredRecords; |
| 73 | |
| 74 | /// Heper for convertType. |
| 75 | mlir::Type convertFunctionTypeInternal(clang::QualType ft); |
| 76 | |
| 77 | public: |
| 78 | CIRGenTypes(CIRGenModule &cgm); |
| 79 | ~CIRGenTypes(); |
| 80 | |
| 81 | CIRGenBuilderTy &getBuilder() const { return builder; } |
| 82 | CIRGenModule &getCGModule() const { return cgm; } |
| 83 | |
| 84 | /// Utility to check whether a function type can be converted to a CIR type |
| 85 | /// (i.e. doesn't depend on an incomplete tag type). |
| 86 | bool isFuncTypeConvertible(const clang::FunctionType *ft); |
| 87 | bool isFuncParamTypeConvertible(clang::QualType type); |
| 88 | |
| 89 | /// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR |
| 90 | /// qualification. |
| 91 | clang::CanQualType deriveThisType(const clang::CXXRecordDecl *rd, |
| 92 | const clang::CXXMethodDecl *md); |
| 93 | |
| 94 | /// This map of clang::Type to mlir::Type (which includes CIR type) is a |
| 95 | /// cache of types that have already been processed. |
| 96 | using TypeCacheTy = llvm::DenseMap<const clang::Type *, mlir::Type>; |
| 97 | TypeCacheTy typeCache; |
| 98 | |
| 99 | mlir::MLIRContext &getMLIRContext() const; |
| 100 | clang::ASTContext &getASTContext() const { return astContext; } |
| 101 | |
| 102 | bool isRecordLayoutComplete(const clang::Type *ty) const; |
| 103 | bool noRecordsBeingLaidOut() const { return recordsBeingLaidOut.empty(); } |
| 104 | bool isRecordBeingLaidOut(const clang::Type *ty) const { |
| 105 | return recordsBeingLaidOut.count(Ptr: ty); |
| 106 | } |
| 107 | |
| 108 | const ABIInfo &getABIInfo() const { return theABIInfo; } |
| 109 | |
| 110 | /// Convert a Clang type into a mlir::Type. |
| 111 | mlir::Type convertType(clang::QualType type); |
| 112 | |
| 113 | mlir::Type convertRecordDeclType(const clang::RecordDecl *recordDecl); |
| 114 | |
| 115 | std::unique_ptr<CIRGenRecordLayout> |
| 116 | computeRecordLayout(const clang::RecordDecl *rd, cir::RecordType *ty); |
| 117 | |
| 118 | std::string getRecordTypeName(const clang::RecordDecl *, |
| 119 | llvm::StringRef suffix); |
| 120 | |
| 121 | const CIRGenRecordLayout &getCIRGenRecordLayout(const clang::RecordDecl *rd); |
| 122 | |
| 123 | /// Convert type T into an mlir::Type. This differs from convertType in that |
| 124 | /// it is used to convert to the memory representation for a type. For |
| 125 | /// example, the scalar representation for bool is i1, but the memory |
| 126 | /// representation is usually i8 or i32, depending on the target. |
| 127 | // TODO: convert this comment to account for MLIR's equivalence |
| 128 | mlir::Type convertTypeForMem(clang::QualType, bool forBitField = false); |
| 129 | |
| 130 | /// Get the CIR function type for \arg Info. |
| 131 | cir::FuncType getFunctionType(const CIRGenFunctionInfo &info); |
| 132 | |
| 133 | // The arrangement methods are split into three families: |
| 134 | // - those meant to drive the signature and prologue/epilogue |
| 135 | // of a function declaration or definition, |
| 136 | // - those meant for the computation of the CIR type for an abstract |
| 137 | // appearance of a function, and |
| 138 | // - those meant for performing the CIR-generation of a call. |
| 139 | // They differ mainly in how they deal with optional (i.e. variadic) |
| 140 | // arguments, as well as unprototyped functions. |
| 141 | // |
| 142 | // Key points: |
| 143 | // - The CIRGenFunctionInfo for emitting a specific call site must include |
| 144 | // entries for the optional arguments. |
| 145 | // - The function type used at the call site must reflect the formal |
| 146 | // signature |
| 147 | // of the declaration being called, or else the call will go away. |
| 148 | // - For the most part, unprototyped functions are called by casting to a |
| 149 | // formal signature inferred from the specific argument types used at the |
| 150 | // call-site. However, some targets (e.g. x86-64) screw with this for |
| 151 | // compatability reasons. |
| 152 | |
| 153 | const CIRGenFunctionInfo &arrangeGlobalDeclaration(GlobalDecl gd); |
| 154 | |
| 155 | /// UpdateCompletedType - when we find the full definition for a TagDecl, |
| 156 | /// replace the 'opaque' type we previously made for it if applicable. |
| 157 | void updateCompletedType(const clang::TagDecl *td); |
| 158 | |
| 159 | /// Free functions are functions that are compatible with an ordinary C |
| 160 | /// function pointer type. |
| 161 | const CIRGenFunctionInfo & |
| 162 | arrangeFunctionDeclaration(const clang::FunctionDecl *fd); |
| 163 | |
| 164 | /// Return whether a type can be zero-initialized (in the C++ sense) with an |
| 165 | /// LLVM zeroinitializer. |
| 166 | bool isZeroInitializable(clang::QualType ty); |
| 167 | bool isZeroInitializable(const RecordDecl *rd); |
| 168 | |
| 169 | const CIRGenFunctionInfo &arrangeCXXConstructorCall( |
| 170 | const CallArgList &args, const clang::CXXConstructorDecl *d, |
| 171 | clang::CXXCtorType ctorKind, bool passProtoArgs = true); |
| 172 | |
| 173 | const CIRGenFunctionInfo & |
| 174 | arrangeCXXMethodCall(const CallArgList &args, |
| 175 | const clang::FunctionProtoType *type, |
| 176 | RequiredArgs required, unsigned numPrefixArgs); |
| 177 | |
| 178 | /// C++ methods have some special rules and also have implicit parameters. |
| 179 | const CIRGenFunctionInfo & |
| 180 | arrangeCXXMethodDeclaration(const clang::CXXMethodDecl *md); |
| 181 | const CIRGenFunctionInfo &arrangeCXXStructorDeclaration(clang::GlobalDecl gd); |
| 182 | |
| 183 | const CIRGenFunctionInfo & |
| 184 | arrangeCXXMethodType(const clang::CXXRecordDecl *rd, |
| 185 | const clang::FunctionProtoType *ftp, |
| 186 | const clang::CXXMethodDecl *md); |
| 187 | |
| 188 | const CIRGenFunctionInfo &arrangeFreeFunctionCall(const CallArgList &args, |
| 189 | const FunctionType *fnType); |
| 190 | |
| 191 | const CIRGenFunctionInfo & |
| 192 | arrangeCIRFunctionInfo(CanQualType returnType, |
| 193 | llvm::ArrayRef<CanQualType> argTypes, |
| 194 | RequiredArgs required); |
| 195 | |
| 196 | const CIRGenFunctionInfo & |
| 197 | arrangeFreeFunctionType(CanQual<FunctionProtoType> fpt); |
| 198 | const CIRGenFunctionInfo & |
| 199 | arrangeFreeFunctionType(CanQual<FunctionNoProtoType> fnpt); |
| 200 | }; |
| 201 | |
| 202 | } // namespace clang::CIRGen |
| 203 | |
| 204 | #endif |
| 205 | |