1//==-- SwiftCallingConv.h - Swift ABI lowering -----------------------------==//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Defines constants and types related to Swift ABI lowering.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_CODEGEN_SWIFTCALLINGCONV_H
15#define LLVM_CLANG_CODEGEN_SWIFTCALLINGCONV_H
16
17#include "clang/AST/CanonicalType.h"
18#include "clang/AST/CharUnits.h"
19#include "clang/AST/Type.h"
20#include "llvm/Support/TrailingObjects.h"
21#include <cassert>
22
23namespace llvm {
24  class IntegerType;
25  class Type;
26  class StructType;
27  class VectorType;
28}
29
30namespace clang {
31class Decl;
32class FieldDecl;
33class ASTRecordLayout;
34
35namespace CodeGen {
36class ABIArgInfo;
37class CodeGenModule;
38class CGFunctionInfo;
39
40namespace swiftcall {
41
42class SwiftAggLowering {
43  CodeGenModule &CGM;
44
45  struct StorageEntry {
46    CharUnits Begin;
47    CharUnits End;
48    llvm::Type *Type;
49
50    CharUnits getWidth() const {
51      return End - Begin;
52    }
53  };
54  SmallVector<StorageEntry, 4> Entries;
55  bool Finished = false;
56
57public:
58  SwiftAggLowering(CodeGenModule &CGM) : CGM(CGM) {}
59
60  void addOpaqueData(CharUnits begin, CharUnits end) {
61    addEntry(nullptr, begin, end);
62  }
63
64  void addTypedData(QualType type, CharUnits begin);
65  void addTypedData(const RecordDecl *record, CharUnits begin);
66  void addTypedData(const RecordDecl *record, CharUnits begin,
67                    const ASTRecordLayout &layout);
68  void addTypedData(llvm::Type *type, CharUnits begin);
69  void addTypedData(llvm::Type *type, CharUnits begin, CharUnits end);
70
71  void finish();
72
73  /// Does this lowering require passing any data?
74  bool empty() const {
75    assert(Finished && "didn't finish lowering before calling empty()");
76    return Entries.empty();
77  }
78
79  /// According to the target Swift ABI, should a value with this lowering
80  /// be passed indirectly?
81  ///
82  /// Note that this decision is based purely on the data layout of the
83  /// value and does not consider whether the type is address-only,
84  /// must be passed indirectly to match a function abstraction pattern, or
85  /// anything else that is expected to be handled by high-level lowering.
86  ///
87  /// \param asReturnValue - if true, answer whether it should be passed
88  ///   indirectly as a return value; if false, answer whether it should be
89  ///   passed indirectly as an argument
90  bool shouldPassIndirectly(bool asReturnValue) const;
91
92  using EnumerationCallback =
93    llvm::function_ref<void(CharUnits offset, CharUnits end, llvm::Type *type)>;
94
95  /// Enumerate the expanded components of this type.
96  ///
97  /// The component types will always be legal vector, floating-point,
98  /// integer, or pointer types.
99  void enumerateComponents(EnumerationCallback callback) const;
100
101  /// Return the types for a coerce-and-expand operation.
102  ///
103  /// The first type matches the memory layout of the data that's been
104  /// added to this structure, including explicit [N x i8] arrays for any
105  /// internal padding.
106  ///
107  /// The second type removes any internal padding members and, if only
108  /// one element remains, is simply that element type.
109  std::pair<llvm::StructType*, llvm::Type*> getCoerceAndExpandTypes() const;
110
111private:
112  void addBitFieldData(const FieldDecl *field, CharUnits begin,
113                       uint64_t bitOffset);
114  void addLegalTypedData(llvm::Type *type, CharUnits begin, CharUnits end);
115  void addEntry(llvm::Type *type, CharUnits begin, CharUnits end);
116  void splitVectorEntry(unsigned index);
117};
118
119/// Return the maximum voluntary integer size for the current target.
120CharUnits getMaximumVoluntaryIntegerSize(CodeGenModule &CGM);
121
122/// Return the Swift CC's notion of the natural alignment of a type.
123CharUnits getNaturalAlignment(CodeGenModule &CGM, llvm::Type *type);
124
125/// Is the given integer type "legal" for Swift's perspective on the
126/// current platform?
127bool isLegalIntegerType(CodeGenModule &CGM, llvm::IntegerType *type);
128
129/// Is the given vector type "legal" for Swift's perspective on the
130/// current platform?
131bool isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize,
132                       llvm::VectorType *vectorTy);
133bool isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize,
134                       llvm::Type *eltTy, unsigned numElts);
135
136/// Minimally split a legal vector type.
137std::pair<llvm::Type*, unsigned>
138splitLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize,
139                     llvm::VectorType *vectorTy);
140
141/// Turn a vector type in a sequence of legal component vector types.
142///
143/// The caller may assume that the sum of the data sizes of the resulting
144/// types will equal the data size of the vector type.
145void legalizeVectorType(CodeGenModule &CGM, CharUnits vectorSize,
146                        llvm::VectorType *vectorTy,
147                        llvm::SmallVectorImpl<llvm::Type*> &types);
148
149/// Should a C++ record type be passed and returned indirectly?
150bool shouldPassCXXRecordIndirectly(CodeGenModule &CGM,
151                                   const CXXRecordDecl *record);
152
153/// Classify the rules for how to return a particular type.
154ABIArgInfo classifyReturnType(CodeGenModule &CGM, CanQualType type);
155
156/// Classify the rules for how to pass a particular type.
157ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type);
158
159/// Compute the ABI information of a swiftcall function.  This is a
160/// private interface for Clang.
161void computeABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI);
162
163/// Is swifterror lowered to a register by the target ABI.
164bool isSwiftErrorLoweredInRegister(CodeGenModule &CGM);
165
166} // end namespace swiftcall
167} // end namespace CodeGen
168} // end namespace clang
169
170#endif
171