blob: 82971980440af7aa158cdce5256aabf4688371d0 [file] [log] [blame]
//===--- Signature.h - An IR function signature -----------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the Signature type, which encapsulates all the
// information necessary to call a function value correctly.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_IRGEN_SIGNATURE_H
#define SWIFT_IRGEN_SIGNATURE_H
#include "llvm/IR/Attributes.h"
#include "llvm/IR/CallingConv.h"
#include "swift/AST/Types.h"
#include "swift/Basic/ExternalUnion.h"
namespace llvm {
class FunctionType;
}
namespace clang {
namespace CodeGen {
class CGFunctionInfo;
}
}
namespace swift {
class Identifier;
enum class SILFunctionTypeRepresentation : uint8_t;
class SILType;
namespace irgen {
class IRGenModule;
/// An encapsulation of different foreign calling-convention lowering
/// information we might have. Should be interpreted according to the
/// abstract CC of the formal function type.
class ForeignFunctionInfo {
public:
const clang::CodeGen::CGFunctionInfo *ClangInfo = nullptr;
};
/// An encapsulation of the extra lowering information we might want to
/// store about a coroutine.
///
/// The ABI for yields breaks the yielded values down into a scalar type
/// sequence, much like argument lowering does: indirect yields (either
/// due to abstraction or size) become pointers and direct yields undergo
/// the general expansion algorithm. We then find the longest prefix of
/// the resulting sequence for which the concatenation
/// (continuation function pointer) + prefix + (optional remainder pointer)
/// is a legal return type according to the swiftcall ABI. The remainder
/// pointer must be included whenever the prefix is strict; it points to
/// a structure containing the remainder of the type sequence, with each
/// element naturally aligned.
///
/// For example, suppose the yields are
/// @in Any, @inout Double, @in Int64, Float, Int8, Int16, Int32
/// This is expanded to the legal type sequence:
/// Any*, double*, i64*, float, i8, i16, i32
/// To the beginning is always appended a continuation function pointer:
/// void (...)*, Any*, double*, i64*, float, i8, i16, i32
/// Suppose that the current target can support at most 4 scalar results.
/// Then the final sequence will be:
/// void (...)*, Any*, double*, { i64*, float, i8, i16, i32 }*
///
/// This final sequence becomes the result type of the coroutine's ramp
/// function and (if a yield_many coroutine) its continuation functions.
class CoroutineInfo {
public:
/// The number of yield components that are returned directly in the
/// coroutine return value.
unsigned NumDirectYieldComponents = 0;
};
namespace {
class SignatureExpansion;
}
/// A signature represents something which can actually be called.
class Signature {
using ExtraData = SimpleExternalUnion<void,
ForeignFunctionInfo,
CoroutineInfo>;
llvm::FunctionType *Type;
llvm::AttributeList Attributes;
llvm::CallingConv::ID CallingConv;
ExtraData::Kind ExtraDataKind; // packed with above
ExtraData ExtraDataStorage;
static_assert(ExtraData::union_is_trivially_copyable,
"not trivially copyable");
friend class irgen::SignatureExpansion;
public:
Signature() : Type(nullptr) {}
Signature(llvm::FunctionType *fnType, llvm::AttributeList attrs,
llvm::CallingConv::ID callingConv)
: Type(fnType), Attributes(attrs), CallingConv(callingConv),
ExtraDataKind(ExtraData::kindForMember<void>()) {}
bool isValid() const {
return Type != nullptr;
}
/// Compute the signature of the given type.
///
/// This is a private detail of the implementation of
/// IRGenModule::getSignature(CanSILFunctionType), which is what
/// clients should generally be using.
static Signature getUncached(IRGenModule &IGM,
CanSILFunctionType formalType);
/// Compute the signature of a coroutine's continuation function.
static Signature forCoroutineContinuation(IRGenModule &IGM,
CanSILFunctionType coroType);
llvm::FunctionType *getType() const {
assert(isValid());
return Type;
}
llvm::CallingConv::ID getCallingConv() const {
assert(isValid());
return CallingConv;
}
llvm::AttributeList getAttributes() const {
assert(isValid());
return Attributes;
}
ForeignFunctionInfo getForeignInfo() const {
assert(isValid());
if (auto info =
ExtraDataStorage.dyn_cast<ForeignFunctionInfo>(ExtraDataKind))
return *info;
return ForeignFunctionInfo();
}
CoroutineInfo getCoroutineInfo() const {
assert(isValid());
if (auto info = ExtraDataStorage.dyn_cast<CoroutineInfo>(ExtraDataKind))
return *info;
return CoroutineInfo();
}
// The mutators below should generally only be used when building up
// a callee.
void setType(llvm::FunctionType *type) {
Type = type;
}
llvm::AttributeList &getMutableAttributes() & {
assert(isValid());
return Attributes;
}
};
} // end namespace irgen
} // end namespace swift
#endif