summaryrefslogtreecommitdiff
path: root/clang/lib/CIR/CodeGen/CIRGenTypes.h
blob: e79cdfc9f822441dcf6626d8ae5bb2d5b6e74576 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
//===--- 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<const clang::Type *, std::unique_ptr<CIRGenRecordLayout>>
      cirGenRecordLayouts;

  /// Contains the CIR type for any converted RecordDecl
  llvm::DenseMap<const clang::Type *, cir::RecordType> recordDeclTypes;

  /// Hold memoized CIRGenFunctionInfo results
  llvm::FoldingSet<CIRGenFunctionInfo> 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<const clang::Type *, 4> recordsBeingLaidOut;

  llvm::SmallVector<const clang::RecordDecl *, 8> 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<const clang::Type *, mlir::Type>;
  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<CIRGenRecordLayout>
  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<CanQualType> argTypes,
                         RequiredArgs required);

  const CIRGenFunctionInfo &
  arrangeFreeFunctionType(CanQual<FunctionProtoType> fpt);
  const CIRGenFunctionInfo &
  arrangeFreeFunctionType(CanQual<FunctionNoProtoType> fnpt);
};

} // namespace clang::CIRGen

#endif