Skip to content

[RemoteAST/Reflection] Changes to MetadataReader and its users to track function parameter flags #12421

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 4 commits into from
Oct 17, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1430,6 +1430,11 @@ class ParameterTypeFlags {
bool isInOut() const { return value.contains(InOut); }
bool isShared() const { return value.contains(Shared); }

ParameterTypeFlags withVariadic(bool variadic) const {
return ParameterTypeFlags(variadic ? value | ParameterTypeFlags::Variadic
: value - ParameterTypeFlags::Variadic);
}

ParameterTypeFlags withEscaping(bool escaping) const {
return ParameterTypeFlags(escaping ? value | ParameterTypeFlags::Escaping
: value - ParameterTypeFlags::Escaping);
Expand Down
31 changes: 16 additions & 15 deletions include/swift/Reflection/TypeRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Casting.h"
#include "swift/ABI/MetadataValues.h"
#include "swift/Remote/MetadataReader.h"
#include "swift/Runtime/Unreachable.h"

#include <iostream>
Expand Down Expand Up @@ -331,39 +332,39 @@ class TupleTypeRef final : public TypeRef {
};

class FunctionTypeRef final : public TypeRef {
std::vector<const TypeRef *> Arguments;
using Param = remote::FunctionParam<const TypeRef *>;

std::vector<Param> Parameters;
const TypeRef *Result;
FunctionTypeFlags Flags;

static TypeRefID Profile(const std::vector<const TypeRef *> &Arguments,
const TypeRef *Result,
FunctionTypeFlags Flags) {
static TypeRefID Profile(const std::vector<Param> &Parameters,
const TypeRef *Result, FunctionTypeFlags Flags) {
TypeRefID ID;
for (auto Argument : Arguments) {
ID.addPointer(Argument);
for (const auto &Param : Parameters) {
ID.addString(Param.getLabel().str());
ID.addPointer(Param.getType());
ID.addInteger(static_cast<uint32_t>(Param.getFlags().toRaw()));
}
ID.addPointer(Result);
ID.addInteger(static_cast<uint64_t>(Flags.getIntValue()));
return ID;
}

public:
FunctionTypeRef(std::vector<const TypeRef *> Arguments, const TypeRef *Result,
FunctionTypeRef(std::vector<Param> Params, const TypeRef *Result,
FunctionTypeFlags Flags)
: TypeRef(TypeRefKind::Function), Arguments(Arguments), Result(Result),
Flags(Flags) {}
: TypeRef(TypeRefKind::Function), Parameters(Params), Result(Result),
Flags(Flags) {}

template <typename Allocator>
static const FunctionTypeRef *create(Allocator &A,
std::vector<const TypeRef *> Arguments,
static const FunctionTypeRef *create(Allocator &A, std::vector<Param> Params,
const TypeRef *Result,
FunctionTypeFlags Flags) {
FIND_OR_CREATE_TYPEREF(A, FunctionTypeRef, Arguments, Result, Flags);
FIND_OR_CREATE_TYPEREF(A, FunctionTypeRef, Params, Result, Flags);
}

const std::vector<const TypeRef *> &getArguments() const {
return Arguments;
};
const std::vector<Param> &getParameters() const { return Parameters; };

const TypeRef *getResult() const {
return Result;
Expand Down
12 changes: 4 additions & 8 deletions include/swift/Reflection/TypeRefBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,14 +209,10 @@ class TypeRefBuilder {
return TupleTypeRef::create(*this, elements, isVariadic);
}

const FunctionTypeRef *
createFunctionType(const std::vector<const TypeRef *> &args,
const std::vector<bool> &inOutArgs,
const TypeRef *result,
FunctionTypeFlags flags) {
// FIXME: don't ignore inOutArgs
// and add test to unittests/Reflection/TypeRef.cpp
return FunctionTypeRef::create(*this, args, result, flags);
const FunctionTypeRef *createFunctionType(
const std::vector<remote::FunctionParam<const TypeRef *>> &params,
const TypeRef *result, FunctionTypeFlags flags) {
return FunctionTypeRef::create(*this, params, result, flags);
}

const ProtocolTypeRef *createProtocolType(const std::string &mangledName,
Expand Down
167 changes: 121 additions & 46 deletions include/swift/Remote/MetadataReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#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 @@ -29,6 +30,43 @@
namespace swift {
namespace remote {

template <typename BuiltType> class FunctionParam {
StringRef Label;
BuiltType Type;
ParameterTypeFlags Flags;

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

public:
explicit FunctionParam() {}

FunctionParam(BuiltType type) : Type(type) {}

StringRef getLabel() const { return Label; }
BuiltType getType() const { return Type; }
ParameterTypeFlags 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); }

FunctionParam withLabel(StringRef label) const {
return FunctionParam(label, Type, Flags);
}

FunctionParam withType(BuiltType type) const {
return FunctionParam(Label, type, Flags);
}

FunctionParam withFlags(ParameterTypeFlags flags) const {
return FunctionParam(Label, Type, flags);
}
};

/// A utility class for constructing abstract types from
/// a textual mangling.
template <typename BuilderType>
Expand Down Expand Up @@ -219,16 +257,14 @@ class TypeDecoder {
Node->getChild(0)->getKind() == NodeKind::ThrowsAnnotation;
flags = flags.withThrows(true);

std::vector<BuiltType> arguments;
std::vector<bool> argsAreInOut;
std::vector<FunctionParam<BuiltType>> parameters;
if (!decodeMangledFunctionInputType(Node->getChild(isThrow ? 1 : 0),
arguments, argsAreInOut, flags))
parameters))
return BuiltType();

auto result = decodeMangledType(Node->getChild(isThrow ? 2 : 1));
if (!result) return BuiltType();
return Builder.createFunctionType(arguments, argsAreInOut,
result, flags);
return Builder.createFunctionType(parameters, result, flags);
}
case NodeKind::ImplFunctionType: {
// Minimal support for lowered function types. These come up in
Expand Down Expand Up @@ -263,15 +299,13 @@ class TypeDecoder {
}

// Completely punt on argument types and results.
std::vector<BuiltType> arguments;
std::vector<bool> argsAreInOut;
std::vector<FunctionParam<BuiltType>> parameters;

std::vector<BuiltType> elements;
std::string labels;
auto result = Builder.createTupleType(elements, std::move(labels), false);

return Builder.createFunctionType(arguments, argsAreInOut,
result, flags);
return Builder.createFunctionType(parameters, result, flags);
}
case NodeKind::ArgumentTuple:
return decodeMangledType(Node->getChild(0));
Expand Down Expand Up @@ -397,55 +431,92 @@ class TypeDecoder {
return true;
}

bool decodeMangledFunctionInputType(const Demangle::NodePointer &node,
std::vector<BuiltType> &args,
std::vector<bool> &argsAreInOut,
FunctionTypeFlags &flags) {
bool decodeMangledFunctionInputType(
const Demangle::NodePointer &node,
std::vector<FunctionParam<BuiltType>> &params) {
// Look through a couple of sugar nodes.
if (node->getKind() == NodeKind::Type ||
node->getKind() == NodeKind::ArgumentTuple) {
return decodeMangledFunctionInputType(node->getFirstChild(),
args, argsAreInOut, flags);
return decodeMangledFunctionInputType(node->getFirstChild(), params);
}

auto decodeSingleHelper =
[&](const Demangle::NodePointer &typeNode, bool argIsInOut) -> bool {
BuiltType argType = decodeMangledType(typeNode);
if (!argType) return false;
auto decodeParamTypeAndFlags =
[&](const Demangle::NodePointer &typeNode,
FunctionParam<BuiltType> &param) -> bool {
Demangle::NodePointer node = typeNode;
switch (node->getKind()) {
case NodeKind::InOut:
param.setInOut();
node = node->getFirstChild();
break;

case NodeKind::Shared:
param.setShared();
node = node->getFirstChild();
break;

default:
break;
}

auto paramType = decodeMangledType(node);
if (!paramType)
return false;

args.push_back(argType);
argsAreInOut.push_back(argIsInOut);
param.setType(paramType);
return true;
};
auto decodeSingle =
[&](const Demangle::NodePointer &typeNode) -> bool {
if (typeNode->getKind() == NodeKind::InOut) {
return decodeSingleHelper(typeNode->getFirstChild(), true);
} else {
return decodeSingleHelper(typeNode, false);

auto decodeParam = [&](const Demangle::NodePointer &paramNode)
-> Optional<FunctionParam<BuiltType>> {
if (paramNode->getKind() != NodeKind::TupleElement)
return None;

FunctionParam<BuiltType> param;
for (const auto &child : *paramNode) {
switch (child->getKind()) {
case NodeKind::TupleElementName:
param.setLabel(child->getText());
break;

case NodeKind::VariadicMarker:
param.setVariadic();
break;

case NodeKind::Type:
if (!decodeParamTypeAndFlags(child->getFirstChild(), param))
return None;
break;

default:
return None;
}
}

return param;
};

// Expand a single level of tuple.
if (node->getKind() == NodeKind::Tuple) {
// TODO: preserve variadic somewhere?

// Decode all the elements as separate arguments.
for (const auto &elt : *node) {
if (elt->getKind() != NodeKind::TupleElement)
return false;
auto typeNode = elt->getChild(elt->getNumChildren() - 1);
if (typeNode->getKind() != NodeKind::Type)
return false;
if (!decodeSingle(typeNode->getFirstChild()))
auto param = decodeParam(elt);
if (!param)
return false;

params.push_back(std::move(*param));
}

return true;
}

// Otherwise, handle the type as a single argument.
return decodeSingle(node);
FunctionParam<BuiltType> param;
if (!decodeParamTypeAndFlags(node, param))
return false;

params.push_back(std::move(param));
return true;
}
};

Expand Down Expand Up @@ -734,8 +805,7 @@ class MetadataReader {
case MetadataKind::Function: {
auto Function = cast<TargetFunctionTypeMetadata<Runtime>>(Meta);

std::vector<BuiltType> Arguments;
std::vector<bool> ArgumentIsInOut;
std::vector<FunctionParam<BuiltType>> Parameters;
StoredPointer ArgumentAddress = MetadataAddress +
sizeof(TargetFunctionTypeMetadata<Runtime>);
for (StoredPointer i = 0; i < Function->getNumArguments(); ++i,
Expand All @@ -745,15 +815,21 @@ class MetadataReader {
&FlaggedArgumentAddress))
return BuiltType();

FunctionParam<BuiltType> Param;

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

if (auto ArgumentTypeRef = readTypeFromMetadata(FlaggedArgumentAddress))
Arguments.push_back(ArgumentTypeRef);
else
FlaggedArgumentAddress &= ~InOutMask;
Copy link
Member

Choose a reason for hiding this comment

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

shared and variadic, too? It's odd to have them partially-supported, so I suggest either completing support or leaving a FIXME to do it all later.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, that's the next step after MetadataReader is updated to support these flags I'm going to update function metadata itself to include all of the flags for parameters...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a FIXME about it on L807, going to address after this changes are in.

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

auto Result = readTypeFromMetadata(Function->ResultType);
Expand All @@ -762,9 +838,8 @@ class MetadataReader {

auto flags = FunctionTypeFlags().withConvention(Function->getConvention())
.withThrows(Function->throws());
auto BuiltFunction = Builder.createFunctionType(Arguments,
ArgumentIsInOut,
Result, flags);
auto BuiltFunction =
Builder.createFunctionType(Parameters, Result, flags);
TypeCache[MetadataAddress] = BuiltFunction;
return BuiltFunction;
}
Expand Down
Loading