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