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
27namespace clang {
28class ASTContext;
29class FunctionType;
30class GlobalDecl;
31class QualType;
32class Type;
33} // namespace clang
34
35namespace mlir {
36class Type;
37}
38
39namespace clang::CIRGen {
40
41class CallArgList;
42class CIRGenBuilderTy;
43class CIRGenCXXABI;
44class CIRGenModule;
45
46/// This class organizes the cross-module state that is used while lowering
47/// AST types to CIR types.
48class 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
77public:
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

source code of clang/lib/CIR/CodeGen/CIRGenTypes.h