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 getBuilder()81 CIRGenBuilderTy &getBuilder() const { return builder; } getCGModule()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; getASTContext()100 clang::ASTContext &getASTContext() const { return astContext; } 101 102 bool isRecordLayoutComplete(const clang::Type *ty) const; noRecordsBeingLaidOut()103 bool noRecordsBeingLaidOut() const { return recordsBeingLaidOut.empty(); } isRecordBeingLaidOut(const clang::Type * ty)104 bool isRecordBeingLaidOut(const clang::Type *ty) const { 105 return recordsBeingLaidOut.count(ty); 106 } 107 getABIInfo()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