Skip to content

Commit

Permalink
IRGen-level lowering for the Swift calling convention.
Browse files Browse the repository at this point in the history
llvm-svn: 265324
  • Loading branch information
rjmccall committed Apr 4, 2016
1 parent b8fa654 commit 12f2352
Show file tree
Hide file tree
Showing 12 changed files with 1,894 additions and 45 deletions.
168 changes: 168 additions & 0 deletions clang/include/clang/CodeGen/SwiftCallingConv.h
@@ -0,0 +1,168 @@
//==-- SwiftCallingConv.h - Swift ABI lowering -----------------------------==//
//
// 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/ADT/FoldingSet.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, 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);
};

/// 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);

/// Should a C++ record type be passed and returned indirectly?
bool shouldPassCXXRecordIndirectly(CodeGenModule &CGM,
const CXXRecordDecl *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);

} // end namespace swiftcall
} // end namespace CodeGen
} // end namespace clang

#endif
51 changes: 43 additions & 8 deletions clang/lib/CodeGen/ABIInfo.h
Expand Up @@ -18,20 +18,25 @@ namespace llvm {
class Value;
class LLVMContext;
class DataLayout;
class Type;
}

namespace clang {
class ASTContext;
class TargetInfo;

namespace CodeGen {
class ABIArgInfo;
class Address;
class CGCXXABI;
class CGFunctionInfo;
class CodeGenFunction;
class CodeGenTypes;
}
namespace CodeGen {
class ABIArgInfo;
class Address;
class CGCXXABI;
class CGFunctionInfo;
class CodeGenFunction;
class CodeGenTypes;
class SwiftABIInfo;

namespace swiftcall {
class SwiftAggLowering;
}

// FIXME: All of this stuff should be part of the target interface
// somehow. It is currently here because it is not clear how to factor
Expand All @@ -55,6 +60,8 @@ namespace clang {

virtual ~ABIInfo();

virtual bool supportsSwift() const { return false; }

CodeGen::CGCXXABI &getCXXABI() const;
ASTContext &getContext() const;
llvm::LLVMContext &getVMContext() const;
Expand Down Expand Up @@ -112,7 +119,35 @@ namespace clang {

CodeGen::ABIArgInfo
getNaturalAlignIndirectInReg(QualType Ty, bool Realign = false) const;


};

/// A refining implementation of ABIInfo for targets that support swiftcall.
///
/// If we find ourselves wanting multiple such refinements, they'll probably
/// be independent refinements, and we should probably find another way
/// to do it than simple inheritance.
class SwiftABIInfo : public ABIInfo {
public:
SwiftABIInfo(CodeGen::CodeGenTypes &cgt) : ABIInfo(cgt) {}

bool supportsSwift() const final override { return true; }

virtual bool shouldPassIndirectlyForSwift(CharUnits totalSize,
ArrayRef<llvm::Type*> types,
bool asReturnValue) const = 0;

virtual bool isLegalVectorTypeForSwift(CharUnits totalSize,
llvm::Type *eltTy,
unsigned elts) const;

static bool classof(const ABIInfo *info) {
return info->supportsSwift();
}
};

} // end namespace CodeGen
} // end namespace clang

#endif

0 comments on commit 12f2352

Please sign in to comment.