//==-- SwiftCallingConv.h - Swift ABI lowering ------------------*- C++ -*-===//
|
//
|
// The LLVM Compiler Infrastructure
|
//
|
// This file is distributed under the University of Illinois Open Source
|
// License. See LICENSE.TXT for details.
|
//
|
//===----------------------------------------------------------------------===//
|
//
|
// Defines constants and types related to Swift ABI lowering.
|
//
|
//===----------------------------------------------------------------------===//
|
|
#ifndef LLVM_CLANG_CODEGEN_SWIFTCALLINGCONV_H
|
#define LLVM_CLANG_CODEGEN_SWIFTCALLINGCONV_H
|
|
#include "clang/AST/CanonicalType.h"
|
#include "clang/AST/CharUnits.h"
|
#include "clang/AST/Type.h"
|
#include "llvm/Support/TrailingObjects.h"
|
#include <cassert>
|
|
namespace llvm {
|
class IntegerType;
|
class Type;
|
class StructType;
|
class VectorType;
|
}
|
|
namespace clang {
|
class Decl;
|
class FieldDecl;
|
class ASTRecordLayout;
|
|
namespace CodeGen {
|
class ABIArgInfo;
|
class CodeGenModule;
|
class CGFunctionInfo;
|
|
namespace swiftcall {
|
|
class SwiftAggLowering {
|
CodeGenModule &CGM;
|
|
struct StorageEntry {
|
CharUnits Begin;
|
CharUnits End;
|
llvm::Type *Type;
|
|
CharUnits getWidth() const {
|
return End - Begin;
|
}
|
};
|
SmallVector<StorageEntry, 4> Entries;
|
bool Finished = false;
|
|
public:
|
SwiftAggLowering(CodeGenModule &CGM) : CGM(CGM) {}
|
|
void addOpaqueData(CharUnits begin, CharUnits end) {
|
addEntry(nullptr, begin, end);
|
}
|
|
void addTypedData(QualType type, CharUnits begin);
|
void addTypedData(const RecordDecl *record, CharUnits begin);
|
void addTypedData(const RecordDecl *record, CharUnits begin,
|
const ASTRecordLayout &layout);
|
void addTypedData(llvm::Type *type, CharUnits begin);
|
void addTypedData(llvm::Type *type, CharUnits begin, CharUnits end);
|
|
void finish();
|
|
/// Does this lowering require passing any data?
|
bool empty() const {
|
assert(Finished && "didn't finish lowering before calling empty()");
|
return Entries.empty();
|
}
|
|
/// According to the target Swift ABI, should a value with this lowering
|
/// be passed indirectly?
|
///
|
/// Note that this decision is based purely on the data layout of the
|
/// value and does not consider whether the type is address-only,
|
/// must be passed indirectly to match a function abstraction pattern, or
|
/// anything else that is expected to be handled by high-level lowering.
|
///
|
/// \param asReturnValue - if true, answer whether it should be passed
|
/// indirectly as a return value; if false, answer whether it should be
|
/// passed indirectly as an argument
|
bool shouldPassIndirectly(bool asReturnValue) const;
|
|
using EnumerationCallback =
|
llvm::function_ref<void(CharUnits offset, CharUnits end, llvm::Type *type)>;
|
|
/// Enumerate the expanded components of this type.
|
///
|
/// The component types will always be legal vector, floating-point,
|
/// integer, or pointer types.
|
void enumerateComponents(EnumerationCallback callback) const;
|
|
/// Return the types for a coerce-and-expand operation.
|
///
|
/// The first type matches the memory layout of the data that's been
|
/// added to this structure, including explicit [N x i8] arrays for any
|
/// internal padding.
|
///
|
/// The second type removes any internal padding members and, if only
|
/// one element remains, is simply that element type.
|
std::pair<llvm::StructType*, llvm::Type*> getCoerceAndExpandTypes() const;
|
|
private:
|
void addBitFieldData(const FieldDecl *field, CharUnits begin,
|
uint64_t bitOffset);
|
void addLegalTypedData(llvm::Type *type, CharUnits begin, CharUnits end);
|
void addEntry(llvm::Type *type, CharUnits begin, CharUnits end);
|
void splitVectorEntry(unsigned index);
|
};
|
|
/// Should an aggregate which expands to the given type sequence
|
/// be passed/returned indirectly under swiftcall?
|
bool shouldPassIndirectly(CodeGenModule &CGM,
|
ArrayRef<llvm::Type*> types,
|
bool asReturnValue);
|
|
/// Return the maximum voluntary integer size for the current target.
|
CharUnits getMaximumVoluntaryIntegerSize(CodeGenModule &CGM);
|
|
/// Return the Swift CC's notion of the natural alignment of a type.
|
CharUnits getNaturalAlignment(CodeGenModule &CGM, llvm::Type *type);
|
|
/// Is the given integer type "legal" for Swift's perspective on the
|
/// current platform?
|
bool isLegalIntegerType(CodeGenModule &CGM, llvm::IntegerType *type);
|
|
/// Is the given vector type "legal" for Swift's perspective on the
|
/// current platform?
|
bool isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize,
|
llvm::VectorType *vectorTy);
|
bool isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize,
|
llvm::Type *eltTy, unsigned numElts);
|
|
/// Minimally split a legal vector type.
|
std::pair<llvm::Type*, unsigned>
|
splitLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize,
|
llvm::VectorType *vectorTy);
|
|
/// Turn a vector type in a sequence of legal component vector types.
|
///
|
/// The caller may assume that the sum of the data sizes of the resulting
|
/// types will equal the data size of the vector type.
|
void legalizeVectorType(CodeGenModule &CGM, CharUnits vectorSize,
|
llvm::VectorType *vectorTy,
|
llvm::SmallVectorImpl<llvm::Type*> &types);
|
|
/// Is the given record type required to be passed and returned indirectly
|
/// because of language restrictions?
|
///
|
/// This considers *only* mandatory indirectness due to language restrictions,
|
/// such as C++'s non-trivially-copyable types and Objective-C's __weak
|
/// references. A record for which this returns true may still be passed
|
/// indirectly for other reasons, such as being too large to fit in a
|
/// reasonable number of registers.
|
bool mustPassRecordIndirectly(CodeGenModule &CGM, const RecordDecl *record);
|
|
/// Classify the rules for how to return a particular type.
|
ABIArgInfo classifyReturnType(CodeGenModule &CGM, CanQualType type);
|
|
/// Classify the rules for how to pass a particular type.
|
ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type);
|
|
/// Compute the ABI information of a swiftcall function. This is a
|
/// private interface for Clang.
|
void computeABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI);
|
|
/// Is swifterror lowered to a register by the target ABI?
|
bool isSwiftErrorLoweredInRegister(CodeGenModule &CGM);
|
|
} // end namespace swiftcall
|
} // end namespace CodeGen
|
} // end namespace clang
|
|
#endif
|