xref: /freebsd/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenTypes.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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