Skip to content

[IRGen] Improvements to function type metadata #12500

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Nov 7, 2017
80 changes: 69 additions & 11 deletions include/swift/ABI/MetadataValues.h
Original file line number Diff line number Diff line change
Expand Up @@ -550,19 +550,21 @@ enum class FunctionMetadataConvention: uint8_t {
template <typename int_type>
class TargetFunctionTypeFlags {
enum : int_type {
NumArgumentsMask = 0x00FFFFFFU,
ConventionMask = 0x0F000000U,
ConventionShift = 24U,
ThrowsMask = 0x10000000U,
NumParametersMask = 0x00FFFFFFU,
ConventionMask = 0x0F000000U,
ConventionShift = 25U,
ThrowsMask = 0x10000000U,
ParamFlagsMask = 0x01000000U,
};
int_type Data;

constexpr TargetFunctionTypeFlags(int_type Data) : Data(Data) {}
public:
constexpr TargetFunctionTypeFlags() : Data(0) {}

constexpr TargetFunctionTypeFlags withNumArguments(unsigned numArguments) const {
return TargetFunctionTypeFlags((Data & ~NumArgumentsMask) | numArguments);
constexpr TargetFunctionTypeFlags
withNumParameters(unsigned numParams) const {
return TargetFunctionTypeFlags((Data & ~NumParametersMask) | numParams);
}

constexpr TargetFunctionTypeFlags<int_type>
Expand All @@ -576,19 +578,25 @@ class TargetFunctionTypeFlags {
return TargetFunctionTypeFlags<int_type>((Data & ~ThrowsMask) |
(throws ? ThrowsMask : 0));
}

unsigned getNumArguments() const {
return Data & NumArgumentsMask;

constexpr TargetFunctionTypeFlags<int_type>
withParameterFlags(bool hasFlags) const {
return TargetFunctionTypeFlags<int_type>((Data & ~ParamFlagsMask) |
(hasFlags ? ParamFlagsMask : 0));
}


unsigned getNumParameters() const { return Data & NumParametersMask; }

FunctionMetadataConvention getConvention() const {
return FunctionMetadataConvention((Data&ConventionMask) >> ConventionShift);
}

bool throws() const {
return bool(Data & ThrowsMask);
}


bool hasParameterFlags() const { return bool(Data & ParamFlagsMask); }

int_type getIntValue() const {
return Data;
}
Expand All @@ -606,6 +614,56 @@ class TargetFunctionTypeFlags {
};
using FunctionTypeFlags = TargetFunctionTypeFlags<size_t>;

template <typename int_type>
class TargetParameterTypeFlags {
enum : int_type {
InOutMask = 1 << 0,
SharedMask = 1 << 1,
VariadicMask = 1 << 2,
};
int_type Data;

constexpr TargetParameterTypeFlags(int_type Data) : Data(Data) {}

public:
constexpr TargetParameterTypeFlags() : Data(0) {}

constexpr TargetParameterTypeFlags<int_type> withInOut(bool isInOut) const {
return TargetParameterTypeFlags<int_type>((Data & ~InOutMask) |
(isInOut ? InOutMask : 0));
}

constexpr TargetParameterTypeFlags<int_type> withShared(bool isShared) const {
return TargetParameterTypeFlags<int_type>((Data & ~SharedMask) |
(isShared ? SharedMask : 0));
}

constexpr TargetParameterTypeFlags<int_type>
withVariadic(bool isVariadic) const {
return TargetParameterTypeFlags<int_type>((Data & ~VariadicMask) |
(isVariadic ? VariadicMask : 0));
}

bool isNone() const { return Data == 0; }
bool isInOut() const { return Data & InOutMask; }
bool isShared() const { return Data & SharedMask; }
bool isVariadic() const { return Data & VariadicMask; }

int_type getIntValue() const { return Data; }

static TargetParameterTypeFlags<int_type> fromIntValue(int_type Data) {
return TargetParameterTypeFlags(Data);
}

bool operator==(TargetParameterTypeFlags<int_type> other) const {
return Data == other.Data;
}
bool operator!=(TargetParameterTypeFlags<int_type> other) const {
return Data != other.Data;
}
};
using ParameterFlags = TargetParameterTypeFlags<uint32_t>;

/// Field types and flags as represented in a nominal type's field/case type
/// vector.
class FieldType {
Expand Down
2 changes: 1 addition & 1 deletion include/swift/Reflection/TypeRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ class FunctionTypeRef final : public TypeRef {
for (const auto &Param : Parameters) {
ID.addString(Param.getLabel().str());
ID.addPointer(Param.getType());
ID.addInteger(static_cast<uint32_t>(Param.getFlags().toRaw()));
ID.addInteger(static_cast<uint32_t>(Param.getFlags().getIntValue()));
}
ID.addPointer(Result);
ID.addInteger(static_cast<uint64_t>(Flags.getIntValue()));
Expand Down
68 changes: 38 additions & 30 deletions include/swift/Remote/MetadataReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#ifndef SWIFT_REMOTE_METADATAREADER_H
#define SWIFT_REMOTE_METADATAREADER_H

#include "swift/AST/Types.h"
#include "swift/Runtime/Metadata.h"
#include "swift/Remote/MemoryReader.h"
#include "swift/Demangling/Demangler.h"
Expand All @@ -33,9 +32,9 @@ namespace remote {
template <typename BuiltType> class FunctionParam {
StringRef Label;
BuiltType Type;
ParameterTypeFlags Flags;
ParameterFlags Flags;

FunctionParam(StringRef label, BuiltType type, ParameterTypeFlags flags)
FunctionParam(StringRef label, BuiltType type, ParameterFlags flags)
: Label(label), Type(type), Flags(flags) {}

public:
Expand All @@ -45,14 +44,15 @@ template <typename BuiltType> class FunctionParam {

StringRef getLabel() const { return Label; }
BuiltType getType() const { return Type; }
ParameterTypeFlags getFlags() const { return Flags; }
ParameterFlags getFlags() const { return Flags; }

void setLabel(StringRef label) { Label = label; }
void setType(BuiltType type) { Type = type; }

void setVariadic() { Flags = Flags.withVariadic(true); }
void setShared() { Flags = Flags.withShared(true); }
void setInOut() { Flags = Flags.withInOut(true); }
void setFlags(ParameterFlags flags) { Flags = flags; };

FunctionParam withLabel(StringRef label) const {
return FunctionParam(label, Type, Flags);
Expand All @@ -62,7 +62,7 @@ template <typename BuiltType> class FunctionParam {
return FunctionParam(Label, type, Flags);
}

FunctionParam withFlags(ParameterTypeFlags flags) const {
FunctionParam withFlags(ParameterFlags flags) const {
return FunctionParam(Label, Type, flags);
}
};
Expand Down Expand Up @@ -798,40 +798,32 @@ class MetadataReader {
}
case MetadataKind::Function: {
auto Function = cast<TargetFunctionTypeMetadata<Runtime>>(Meta);
auto *const parameters = Function->getParameters();

std::vector<FunctionParam<BuiltType>> Parameters;
StoredPointer ArgumentAddress = MetadataAddress +
sizeof(TargetFunctionTypeMetadata<Runtime>);
for (StoredPointer i = 0; i < Function->getNumArguments(); ++i,
ArgumentAddress += sizeof(StoredPointer)) {
StoredPointer FlaggedArgumentAddress;
if (!Reader->readInteger(RemoteAddress(ArgumentAddress),
&FlaggedArgumentAddress))
for (unsigned i = 0, n = Function->getNumParameters(); i != n; ++i) {
StoredPointer ParamMetadata;
if (!Reader->readInteger(RemoteAddress(parameters + i), &ParamMetadata))
return BuiltType();

FunctionParam<BuiltType> Param;

// TODO: Use target-agnostic FlaggedPointer to mask this!
const auto InOutMask = (StoredPointer) 1;
// FIXME: Add import parameter related flags from metadata
if ((FlaggedArgumentAddress & InOutMask) != 0)
Param.setInOut();

FlaggedArgumentAddress &= ~InOutMask;
if (auto ParamTypeRef = readTypeFromMetadata(FlaggedArgumentAddress)) {
Param.setType(ParamTypeRef);
Parameters.push_back(std::move(Param));
} else {
auto ParamTypeRef = readTypeFromMetadata(ParamMetadata);
if (!ParamTypeRef)
return BuiltType();
}

FunctionParam<BuiltType> Param;
Param.setType(ParamTypeRef);
Param.setFlags(Function->getParameterFlags(i));
Parameters.push_back(std::move(Param));
}

auto Result = readTypeFromMetadata(Function->ResultType);
if (!Result)
return BuiltType();

auto flags = FunctionTypeFlags().withConvention(Function->getConvention())
.withThrows(Function->throws());
auto flags = FunctionTypeFlags()
.withConvention(Function->getConvention())
.withThrows(Function->throws())
.withParameterFlags(Function->hasParameterFlags());
auto BuiltFunction =
Builder.createFunctionType(Parameters, Result, flags);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you'll need to change the createFunctionType API to also take parameter flags, which probably means remapping them to the AST flags.

Also, what I mean about TupleMetadata is that you should modify the MetadataKind::Function case in readMetadata to start by reading the FunctionTypeMetadata and then use that to figure out the complete size to read, like the case for MetadataKind::Tuple does.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok, I think I understand know, I thought you meant treat flags like labels are treated in case of tuple...

Regarding createFunctionType API - each of the elements in Parameters already has flags attached to it, so I think flags are covered that way?...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, yes, I see, that makes sense.

TypeCache[MetadataAddress] = BuiltFunction;
Expand Down Expand Up @@ -1195,8 +1187,24 @@ class MetadataReader {
return _readMetadata<TargetExistentialMetatypeMetadata>(address);
case MetadataKind::ForeignClass:
return _readMetadata<TargetForeignClassMetadata>(address);
case MetadataKind::Function:
return _readMetadata<TargetFunctionTypeMetadata>(address);
case MetadataKind::Function: {
StoredSize flagsValue;
auto flagsAddr =
address + TargetFunctionTypeMetadata<Runtime>::OffsetToFlags;
if (!Reader->readInteger(RemoteAddress(flagsAddr), &flagsValue))
return nullptr;

auto flags =
TargetFunctionTypeFlags<StoredSize>::fromIntValue(flagsValue);

auto totalSize = sizeof(TargetFunctionTypeMetadata<Runtime>) +
flags.getNumParameters() * sizeof(StoredPointer);

if (flags.hasParameterFlags())
totalSize += flags.getNumParameters() * sizeof(uint32_t);

return _readMetadata(address, totalSize);
}
case MetadataKind::HeapGenericLocalVariable:
return _readMetadata<TargetGenericBoxHeapMetadata>(address);
case MetadataKind::HeapLocalVariable:
Expand Down
84 changes: 63 additions & 21 deletions include/swift/Runtime/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -1745,36 +1745,48 @@ using EnumMetadata = TargetEnumMetadata<InProcess>;
template <typename Runtime>
struct TargetFunctionTypeMetadata : public TargetMetadata<Runtime> {
using StoredSize = typename Runtime::StoredSize;

// TODO: Make this target agnostic
using Argument = FlaggedPointer<const TargetMetadata<Runtime> *, 0>;
using Parameter = const TargetMetadata<Runtime> *;

TargetFunctionTypeFlags<StoredSize> Flags;

/// The type metadata for the result type.
ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> ResultType;

TargetPointer<Runtime, Argument> getArguments() {
return reinterpret_cast<TargetPointer<Runtime, Argument>>(this + 1);
Parameter *getParameters() { return reinterpret_cast<Parameter *>(this + 1); }

const Parameter *getParameters() const {
return reinterpret_cast<const Parameter *>(this + 1);
}

TargetPointer<Runtime, const Argument> getArguments() const {
return reinterpret_cast<TargetPointer<Runtime, const Argument>>(this + 1);
ParameterFlags getParameterFlags(unsigned index) const {
assert(index < getNumParameters());
auto flags = hasParameterFlags() ? getParameterFlags()[index] : 0;
return ParameterFlags::fromIntValue(flags);
}
StoredSize getNumArguments() const {
return Flags.getNumArguments();

StoredSize getNumParameters() const {
return Flags.getNumParameters();
}
FunctionMetadataConvention getConvention() const {
return Flags.getConvention();
}
bool throws() const { return Flags.throws(); }
bool hasParameterFlags() const { return Flags.hasParameterFlags(); }

static constexpr StoredSize OffsetToFlags = sizeof(TargetMetadata<Runtime>);

static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::Function;
}

uint32_t *getParameterFlags() {
return reinterpret_cast<uint32_t *>(getParameters() + getNumParameters());
}

const uint32_t *getParameterFlags() const {
return reinterpret_cast<const uint32_t *>(getParameters() +
getNumParameters());
}
};
using FunctionTypeMetadata = TargetFunctionTypeMetadata<InProcess>;

Expand Down Expand Up @@ -2639,28 +2651,58 @@ swift_getGenericWitnessTable(GenericWitnessTable *genericTable,
/// \brief Fetch a uniqued metadata for a function type.
SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
swift_getFunctionTypeMetadata(const void *flagsArgsAndResult[]);
swift_getFunctionTypeMetadata(FunctionTypeFlags flags,
const Metadata *const *parameters,
const uint32_t *parameterFlags,
const Metadata *result);

SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
swift_getFunctionTypeMetadata1(FunctionTypeFlags flags,
const void *arg0,
const Metadata *resultMetadata);
const Metadata *arg0,
const Metadata *result);

SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
swift_getFunctionTypeMetadata1WithFlags(FunctionTypeFlags flags,
const Metadata *arg0,
ParameterFlags flags0,
const Metadata *result);

SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
swift_getFunctionTypeMetadata2(FunctionTypeFlags flags,
const void *arg0,
const void *arg1,
const Metadata *resultMetadata);
const Metadata *arg0,
const Metadata *arg1,
const Metadata *result);

SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
swift_getFunctionTypeMetadata3(FunctionTypeFlags flags,
const void *arg0,
const void *arg1,
const void *arg2,
const Metadata *resultMetadata);
swift_getFunctionTypeMetadata2WithFlags(FunctionTypeFlags flags,
const Metadata *arg0,
ParameterFlags flags0,
const Metadata *arg1,
ParameterFlags flags1,
const Metadata *result);

SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *swift_getFunctionTypeMetadata3(
FunctionTypeFlags flags,
const Metadata *arg0,
const Metadata *arg1,
const Metadata *arg2,
const Metadata *result);

SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *swift_getFunctionTypeMetadata3WithFlags(
FunctionTypeFlags flags,
const Metadata *arg0,
ParameterFlags flags0,
const Metadata *arg1,
ParameterFlags flags1,
const Metadata *arg2,
ParameterFlags flags2,
const Metadata *result);

/// \brief Fetch a uniqued metadata for a thin function type.
SWIFT_RUNTIME_EXPORT
Expand Down
Loading