in include/swift/Demangling/TypeDecoder.h [483:1285]
TypeLookupErrorOr<BuiltType> decodeMangledType(NodePointer Node,
unsigned depth,
bool forRequirement = true) {
if (depth > TypeDecoder::MaxDepth)
return TypeLookupError("Mangled type is too complex");
if (!Node)
return TypeLookupError("Node is NULL");
using NodeKind = Demangle::Node::Kind;
switch (Node->getKind()) {
case NodeKind::Global:
if (Node->getNumChildren() < 1)
return MAKE_NODE_TYPE_ERROR0(Node, "no children.");
return decodeMangledType(Node->getChild(0), depth + 1);
case NodeKind::TypeMangling:
if (Node->getNumChildren() < 1)
return MAKE_NODE_TYPE_ERROR0(Node, "no children.");
return decodeMangledType(Node->getChild(0), depth + 1);
case NodeKind::Type:
if (Node->getNumChildren() < 1)
return MAKE_NODE_TYPE_ERROR0(Node, "no children.");
return decodeMangledType(Node->getChild(0), depth + 1,
forRequirement);
case NodeKind::Class:
{
#if SWIFT_OBJC_INTEROP
if (auto mangledName = getObjCClassOrProtocolName(Node))
return Builder.createObjCClassType(mangledName->str());
#endif
LLVM_FALLTHROUGH;
}
case NodeKind::Enum:
case NodeKind::Structure:
case NodeKind::TypeAlias:
case NodeKind::TypeSymbolicReference:
{
BuiltTypeDecl typeDecl = BuiltTypeDecl();
BuiltType parent = BuiltType();
bool typeAlias = false;
if (auto error =
decodeMangledTypeDecl(Node, depth, typeDecl, parent, typeAlias))
return *error;
if (typeAlias)
return Builder.createTypeAliasType(typeDecl, parent);
return Builder.createNominalType(typeDecl, parent);
}
case NodeKind::BoundGenericEnum:
case NodeKind::BoundGenericStructure:
case NodeKind::BoundGenericClass:
case NodeKind::BoundGenericTypeAlias:
case NodeKind::BoundGenericOtherNominalType: {
if (Node->getNumChildren() < 2)
return MAKE_NODE_TYPE_ERROR(Node,
"fewer children (%zu) than required (2)",
Node->getNumChildren());
llvm::SmallVector<BuiltType, 8> args;
const auto &genericArgs = Node->getChild(1);
if (genericArgs->getKind() != NodeKind::TypeList)
return MAKE_NODE_TYPE_ERROR0(genericArgs, "is not TypeList");
for (auto genericArg : *genericArgs) {
auto paramType = decodeMangledType(genericArg, depth + 1,
/*forRequirement=*/false);
if (paramType.isError())
return paramType;
args.push_back(paramType.getType());
}
auto ChildNode = Node->getChild(0);
if (ChildNode->getKind() == NodeKind::Type &&
ChildNode->getNumChildren() > 0)
ChildNode = ChildNode->getChild(0);
#if SWIFT_OBJC_INTEROP
if (auto mangledName = getObjCClassOrProtocolName(ChildNode))
return Builder.createBoundGenericObjCClassType(mangledName->str(),
args);
#endif
BuiltTypeDecl typeDecl = BuiltTypeDecl();
BuiltType parent = BuiltType();
bool typeAlias = false;
if (auto error = decodeMangledTypeDecl(ChildNode, depth, typeDecl, parent,
typeAlias))
return *error;
return Builder.createBoundGenericType(typeDecl, args, parent);
}
case NodeKind::BoundGenericProtocol: {
// This is a special case. When you write a protocol typealias with a
// concrete type base, for example:
//
// protocol P { typealias A<T> = ... }
// struct S : P {}
// let x: S.A<Int> = ...
//
// The mangling tree looks like this:
//
// BoundGenericProtocol ---> BoundGenericTypeAlias
// | |
// | |
// --> Protocol: P --> TypeAlias: A
// | |
// --> TypeList: --> TypeList:
// | |
// --> Structure: S --> Structure: Int
//
// When resolving the mangling tree to a decl, we strip off the
// BoundGenericProtocol's *argument*, leaving behind only the
// protocol reference.
//
// But when resolving it to a type, we want to *keep* the argument
// so that the parent type becomes 'S' and not 'P'.
if (Node->getNumChildren() < 2)
return MAKE_NODE_TYPE_ERROR(Node,
"fewer children (%zu) than required (2)",
Node->getNumChildren());
const auto &genericArgs = Node->getChild(1);
if (genericArgs->getNumChildren() != 1)
return MAKE_NODE_TYPE_ERROR(genericArgs,
"expected 1 generic argument, saw %zu",
genericArgs->getNumChildren());
return decodeMangledType(genericArgs->getChild(0), depth + 1);
}
case NodeKind::BuiltinTypeName: {
auto mangling = Demangle::mangleNode(Node);
if (!mangling.isSuccess()) {
return MAKE_NODE_TYPE_ERROR(Node,
"failed to mangle node (%d:%u)",
mangling.error().code,
mangling.error().line);
}
return Builder.createBuiltinType(Node->getText().str(), mangling.result());
}
case NodeKind::Metatype:
case NodeKind::ExistentialMetatype: {
unsigned i = 0;
llvm::Optional<ImplMetatypeRepresentation> repr;
// Handle lowered metatypes in a hackish way. If the representation
// was not thin, force the resulting typeref to have a non-empty
// representation.
if (Node->getNumChildren() >= 2) {
auto reprNode = Node->getChild(i++);
if (reprNode->getKind() != NodeKind::MetatypeRepresentation ||
!reprNode->hasText())
return MAKE_NODE_TYPE_ERROR0(reprNode, "wrong node kind or no text");
if (reprNode->getText() == "@thin")
repr = ImplMetatypeRepresentation::Thin;
else if (reprNode->getText() == "@thick")
repr = ImplMetatypeRepresentation::Thick;
else if (reprNode->getText() == "@objc_metatype")
repr = ImplMetatypeRepresentation::ObjC;
} else if (Node->getNumChildren() < 1) {
return MAKE_NODE_TYPE_ERROR0(Node, "no children");
}
auto instance = decodeMangledType(Node->getChild(i), depth + 1);
if (instance.isError())
return instance;
if (Node->getKind() == NodeKind::Metatype) {
return Builder.createMetatypeType(instance.getType(), repr);
} else if (Node->getKind() == NodeKind::ExistentialMetatype) {
return Builder.createExistentialMetatypeType(instance.getType(), repr);
} else {
assert(false);
return MAKE_NODE_TYPE_ERROR0(Node,
"Metatype/ExistentialMetatype Node "
"had a different kind when re-checked");
}
}
case NodeKind::ProtocolList:
case NodeKind::ProtocolListWithAnyObject:
case NodeKind::ProtocolListWithClass: {
if (Node->getNumChildren() < 1)
return MAKE_NODE_TYPE_ERROR0(Node, "no children");
// Find the protocol list.
llvm::SmallVector<BuiltProtocolDecl, 8> Protocols;
auto TypeList = Node->getChild(0);
if (TypeList->getKind() == NodeKind::ProtocolList &&
TypeList->getNumChildren() >= 1) {
TypeList = TypeList->getChild(0);
}
// Demangle the protocol list.
for (auto componentType : *TypeList) {
if (auto Protocol = decodeMangledProtocolType(componentType, depth + 1))
Protocols.push_back(Protocol);
else
return MAKE_NODE_TYPE_ERROR0(componentType,
"failed to decode protocol type");
}
// Superclass or AnyObject, if present.
bool IsClassBound = false;
auto Superclass = BuiltType();
if (Node->getKind() == NodeKind::ProtocolListWithClass) {
if (Node->getNumChildren() < 2)
return MAKE_NODE_TYPE_ERROR(Node,
"fewer children (%zu) than required (2)",
Node->getNumChildren());
auto superclassNode = Node->getChild(1);
auto result = decodeMangledType(superclassNode, depth + 1);
if (result.isError())
return result;
Superclass = result.getType();
IsClassBound = true;
} else if (Node->getKind() == NodeKind::ProtocolListWithAnyObject) {
IsClassBound = true;
}
return Builder.createProtocolCompositionType(Protocols, Superclass,
IsClassBound,
forRequirement);
}
case NodeKind::Protocol:
case NodeKind::ProtocolSymbolicReference: {
if (auto Proto = decodeMangledProtocolType(Node, depth + 1)) {
return Builder.createProtocolCompositionType(Proto, BuiltType(),
/*IsClassBound=*/false,
forRequirement);
}
return MAKE_NODE_TYPE_ERROR0(Node, "failed to decode protocol type");
}
case NodeKind::DynamicSelf: {
if (Node->getNumChildren() != 1)
return MAKE_NODE_TYPE_ERROR(Node, "expected 1 child, saw %zu",
Node->getNumChildren());
auto selfType = decodeMangledType(Node->getChild(0), depth + 1);
if (selfType.isError())
return selfType;
return Builder.createDynamicSelfType(selfType.getType());
}
case NodeKind::DependentGenericParamType: {
auto depth = Node->getChild(0)->getIndex();
auto index = Node->getChild(1)->getIndex();
return Builder.createGenericTypeParameterType(depth, index);
}
case NodeKind::EscapingObjCBlock:
case NodeKind::ObjCBlock:
case NodeKind::CFunctionPointer:
case NodeKind::ThinFunctionType:
case NodeKind::NoEscapeFunctionType:
case NodeKind::AutoClosureType:
case NodeKind::EscapingAutoClosureType:
case NodeKind::FunctionType: {
if (Node->getNumChildren() < 2)
return MAKE_NODE_TYPE_ERROR(Node,
"fewer children (%zu) than required (2)",
Node->getNumChildren());
FunctionTypeFlags flags;
if (Node->getKind() == NodeKind::ObjCBlock ||
Node->getKind() == NodeKind::EscapingObjCBlock) {
flags = flags.withConvention(FunctionMetadataConvention::Block);
} else if (Node->getKind() == NodeKind::CFunctionPointer) {
flags =
flags.withConvention(FunctionMetadataConvention::CFunctionPointer);
} else if (Node->getKind() == NodeKind::ThinFunctionType) {
flags = flags.withConvention(FunctionMetadataConvention::Thin);
}
unsigned firstChildIdx = 0;
if (Node->getChild(firstChildIdx)->getKind() == NodeKind::ClangType) {
// [TODO: synthesize-Clang-type-from-mangled-name] Use the first child
// to create a ClangTypeInfo.
++firstChildIdx;
}
BuiltType globalActorType = BuiltType();
if (Node->getChild(firstChildIdx)->getKind() ==
NodeKind::GlobalActorFunctionType) {
auto child = Node->getChild(firstChildIdx);
if (child->getNumChildren() < 1) {
return MAKE_NODE_TYPE_ERROR0(child,
"Global actor node is missing child");
}
auto globalActorResult =
decodeMangledType(child->getChild(0), depth + 1);
if (globalActorResult.isError())
return globalActorResult;
globalActorType = globalActorResult.getType();
++firstChildIdx;
}
FunctionMetadataDifferentiabilityKind diffKind;
if (Node->getChild(firstChildIdx)->getKind() ==
NodeKind::DifferentiableFunctionType) {
auto mangledDiffKind = (MangledDifferentiabilityKind)
Node->getChild(firstChildIdx)->getIndex();
switch (mangledDiffKind) {
case MangledDifferentiabilityKind::NonDifferentiable:
assert(false && "Unexpected case NonDifferentiable");
break;
case MangledDifferentiabilityKind::Forward:
diffKind = FunctionMetadataDifferentiabilityKind::Forward;
break;
case MangledDifferentiabilityKind::Reverse:
diffKind = FunctionMetadataDifferentiabilityKind::Reverse;
break;
case MangledDifferentiabilityKind::Normal:
diffKind = FunctionMetadataDifferentiabilityKind::Normal;
break;
case MangledDifferentiabilityKind::Linear:
diffKind = FunctionMetadataDifferentiabilityKind::Linear;
break;
}
++firstChildIdx;
}
bool isThrow = false;
if (Node->getChild(firstChildIdx)->getKind()
== NodeKind::ThrowsAnnotation) {
isThrow = true;
++firstChildIdx;
}
bool isSendable = false;
if (Node->getChild(firstChildIdx)->getKind()
== NodeKind::ConcurrentFunctionType) {
isSendable = true;
++firstChildIdx;
}
bool isAsync = false;
if (Node->getChild(firstChildIdx)->getKind()
== NodeKind::AsyncAnnotation) {
isAsync = true;
++firstChildIdx;
}
flags = flags.withConcurrent(isSendable)
.withAsync(isAsync).withThrows(isThrow)
.withDifferentiable(diffKind.isDifferentiable());
if (Node->getNumChildren() < firstChildIdx + 2)
return MAKE_NODE_TYPE_ERROR(Node,
"fewer children (%zu) than required (%u)",
Node->getNumChildren(), firstChildIdx + 2);
bool hasParamFlags = false;
llvm::SmallVector<FunctionParam<BuiltType>, 8> parameters;
if (!decodeMangledFunctionInputType(Node->getChild(firstChildIdx),
depth + 1, parameters, hasParamFlags))
return MAKE_NODE_TYPE_ERROR0(Node->getChild(firstChildIdx),
"failed to decode function type");
flags =
flags.withNumParameters(parameters.size())
.withParameterFlags(hasParamFlags)
.withEscaping(
Node->getKind() == NodeKind::FunctionType ||
Node->getKind() == NodeKind::EscapingAutoClosureType ||
Node->getKind() == NodeKind::EscapingObjCBlock);
auto result =
decodeMangledType(Node->getChild(firstChildIdx + 1), depth + 1,
/*forRequirement=*/false);
if (result.isError())
return result;
return Builder.createFunctionType(
parameters, result.getType(), flags, diffKind, globalActorType);
}
case NodeKind::ImplFunctionType: {
auto calleeConvention = ImplParameterConvention::Direct_Unowned;
llvm::SmallVector<ImplFunctionParam<BuiltType>, 8> parameters;
llvm::SmallVector<ImplFunctionResult<BuiltType>, 8> results;
llvm::SmallVector<ImplFunctionResult<BuiltType>, 8> errorResults;
ImplFunctionTypeFlags flags;
for (unsigned i = 0; i < Node->getNumChildren(); i++) {
auto child = Node->getChild(i);
if (child->getKind() == NodeKind::ImplConvention) {
if (!child->hasText())
return MAKE_NODE_TYPE_ERROR0(child, "expected text");
if (child->getText() == "@convention(thin)") {
flags =
flags.withRepresentation(ImplFunctionRepresentation::Thin);
} else if (child->getText() == "@callee_guaranteed") {
calleeConvention = ImplParameterConvention::Direct_Guaranteed;
}
} else if (child->getKind() == NodeKind::ImplFunctionConvention) {
if (child->getNumChildren() == 0)
return MAKE_NODE_TYPE_ERROR0(child, "expected grandchildren");
if ((child->getFirstChild()->getKind() !=
NodeKind::ImplFunctionConventionName) ||
!child->getFirstChild()->hasText())
return MAKE_NODE_TYPE_ERROR0(child, "expected convention name");
// [TODO: synthesize-Clang-type-from-mangled-name] If there are two
// grand-children, the second is going to be the mangled Clang type.
StringRef text = child->getFirstChild()->getText();
if (text == "c") {
flags =
flags.withRepresentation(ImplFunctionRepresentation::CFunctionPointer);
} else if (text == "block") {
flags =
flags.withRepresentation(ImplFunctionRepresentation::Block);
}
} else if (child->getKind() == NodeKind::ImplFunctionAttribute) {
if (!child->hasText())
return MAKE_NODE_TYPE_ERROR0(child, "expected text");
if (child->getText() == "@Sendable") {
flags = flags.withConcurrent();
} else if (child->getText() == "@async") {
flags = flags.withAsync();
}
} else if (child->getKind() == NodeKind::ImplDifferentiabilityKind) {
ImplFunctionDifferentiabilityKind implDiffKind;
switch ((MangledDifferentiabilityKind)child->getIndex()) {
#define SIMPLE_CASE(CASE) \
case MangledDifferentiabilityKind::CASE: \
implDiffKind = ImplFunctionDifferentiabilityKind::CASE; break;
SIMPLE_CASE(NonDifferentiable)
SIMPLE_CASE(Normal)
SIMPLE_CASE(Linear)
SIMPLE_CASE(Forward)
SIMPLE_CASE(Reverse)
#undef SIMPLE_CASE
}
flags = flags.withDifferentiabilityKind(implDiffKind);
} else if (child->getKind() == NodeKind::ImplEscaping) {
flags = flags.withEscaping();
} else if (child->getKind() == NodeKind::ImplParameter) {
if (decodeImplFunctionParam(child, depth + 1, parameters))
return MAKE_NODE_TYPE_ERROR0(child,
"failed to decode function parameter");
} else if (child->getKind() == NodeKind::ImplResult) {
if (decodeImplFunctionParam(child, depth + 1, results))
return MAKE_NODE_TYPE_ERROR0(child,
"failed to decode function parameter");
} else if (child->getKind() == NodeKind::ImplErrorResult) {
if (decodeImplFunctionPart(child, depth + 1, errorResults))
return MAKE_NODE_TYPE_ERROR0(child,
"failed to decode function part");
} else {
return MAKE_NODE_TYPE_ERROR0(child, "unexpected kind");
}
}
llvm::Optional<ImplFunctionResult<BuiltType>> errorResult;
switch (errorResults.size()) {
case 0:
break;
case 1:
errorResult = errorResults.front();
break;
default:
return MAKE_NODE_TYPE_ERROR(Node, "got %zu errors",
errorResults.size());
}
// TODO: Some cases not handled above, but *probably* they cannot
// appear as the types of values in SIL (yet?):
// - functions with yield returns
// - functions with generic signatures
// - foreign error conventions
return Builder.createImplFunctionType(calleeConvention,
parameters, results,
errorResult, flags);
}
case NodeKind::ArgumentTuple:
if (Node->getNumChildren() < 1)
return MAKE_NODE_TYPE_ERROR0(Node, "no children");
return decodeMangledType(Node->getChild(0), depth + 1);
case NodeKind::ReturnType:
if (Node->getNumChildren() < 1)
return MAKE_NODE_TYPE_ERROR0(Node, "no children");
return decodeMangledType(Node->getChild(0), depth + 1,
/*forRequirement=*/false);
case NodeKind::Tuple: {
llvm::SmallVector<BuiltType, 8> elements;
std::string labels;
for (auto &element : *Node) {
if (element->getKind() != NodeKind::TupleElement)
return MAKE_NODE_TYPE_ERROR0(Node, "unexpected kind");
// If the tuple element is labeled, add its label to 'labels'.
unsigned typeChildIndex = 0;
if (element->getChild(typeChildIndex)->getKind() == NodeKind::VariadicMarker) {
return MAKE_NODE_TYPE_ERROR0(element->getChild(typeChildIndex),
"no children");
}
if (element->getChild(typeChildIndex)->getKind() == NodeKind::TupleElementName) {
// Add spaces to terminate all the previous labels if this
// is the first we've seen.
if (labels.empty()) labels.append(elements.size(), ' ');
// Add the label and its terminator.
labels += element->getChild(typeChildIndex)->getText();
labels += ' ';
typeChildIndex++;
// Otherwise, add a space if a previous element had a label.
} else if (!labels.empty()) {
labels += ' ';
}
// Decode the element type.
auto elementType =
decodeMangledType(element->getChild(typeChildIndex), depth + 1,
/*forRequirement=*/false);
if (elementType.isError())
return elementType;
elements.push_back(elementType.getType());
}
return Builder.createTupleType(elements, std::move(labels));
}
case NodeKind::TupleElement:
if (Node->getNumChildren() < 1)
return MAKE_NODE_TYPE_ERROR0(Node, "no children");
if (Node->getChild(0)->getKind() == NodeKind::TupleElementName) {
if (Node->getNumChildren() < 2)
return MAKE_NODE_TYPE_ERROR(Node,
"fewer children (%zu) than required (2)",
Node->getNumChildren());
return decodeMangledType(Node->getChild(1), depth + 1,
/*forRequirement=*/false);
}
return decodeMangledType(Node->getChild(0), depth + 1,
/*forRequirement=*/false);
case NodeKind::DependentGenericType: {
if (Node->getNumChildren() < 2)
return MAKE_NODE_TYPE_ERROR(Node,
"fewer children (%zu) than required (2)",
Node->getNumChildren());
return decodeMangledType(Node->getChild(1), depth + 1);
}
case NodeKind::DependentMemberType: {
if (Node->getNumChildren() < 2)
return MAKE_NODE_TYPE_ERROR(Node,
"fewer children (%zu) than required (2)",
Node->getNumChildren());
auto base = decodeMangledType(Node->getChild(0), depth + 1);
if (base.isError())
return base;
auto assocTypeChild = Node->getChild(1);
auto member = assocTypeChild->getFirstChild()->getText();
if (assocTypeChild->getNumChildren() < 2)
return Builder.createDependentMemberType(member.str(), base.getType());
auto protocol =
decodeMangledProtocolType(assocTypeChild->getChild(1), depth + 1);
if (!protocol)
return BuiltType();
return Builder.createDependentMemberType(member.str(), base.getType(),
protocol);
}
case NodeKind::DependentAssociatedTypeRef: {
if (Node->getNumChildren() < 2)
return MAKE_NODE_TYPE_ERROR(Node,
"fewer children (%zu) than required (2)",
Node->getNumChildren());
return decodeMangledType(Node->getChild(1), depth + 1);
}
case NodeKind::Unowned: {
if (Node->getNumChildren() < 1)
return MAKE_NODE_TYPE_ERROR0(Node, "no children");
auto base = decodeMangledType(Node->getChild(0), depth + 1);
if (base.isError())
return base;
return Builder.createUnownedStorageType(base.getType());
}
case NodeKind::Unmanaged: {
if (Node->getNumChildren() < 1)
return MAKE_NODE_TYPE_ERROR0(Node, "no children");
auto base = decodeMangledType(Node->getChild(0), depth + 1);
if (base.isError())
return base;
return Builder.createUnmanagedStorageType(base.getType());
}
case NodeKind::Weak: {
if (Node->getNumChildren() < 1)
return MAKE_NODE_TYPE_ERROR0(Node, "no children");
auto base = decodeMangledType(Node->getChild(0), depth + 1);
if (base.isError())
return base;
return Builder.createWeakStorageType(base.getType());
}
case NodeKind::SILBoxType: {
if (Node->getNumChildren() < 1)
return MAKE_NODE_TYPE_ERROR0(Node, "no children");
auto base = decodeMangledType(Node->getChild(0), depth + 1);
if (base.isError())
return base;
return Builder.createSILBoxType(base.getType());
}
case NodeKind::SILBoxTypeWithLayout: {
llvm::SmallVector<Field, 4> fields;
llvm::SmallVector<BuiltSubstitution, 4> substitutions;
llvm::SmallVector<BuiltRequirement, 4> requirements;
if (Node->getNumChildren() < 1)
return MAKE_NODE_TYPE_ERROR0(Node, "no children");
auto fieldsNode = Node->getChild(0);
if (fieldsNode->getKind() != NodeKind::SILBoxLayout)
return MAKE_NODE_TYPE_ERROR0(fieldsNode, "expected layout");
for (auto *fieldNode : *fieldsNode) {
bool isMutable;
switch (fieldNode->getKind()) {
case NodeKind::SILBoxMutableField: isMutable = true; break;
case NodeKind::SILBoxImmutableField: isMutable = false; break;
default:
return MAKE_NODE_TYPE_ERROR0(fieldNode, "unhandled field type");
}
if (fieldNode->getNumChildren() < 1)
return MAKE_NODE_TYPE_ERROR0(fieldNode, "no children");
auto type = decodeMangledType(fieldNode->getChild(0), depth + 1);
if (type.isError())
return type;
fields.emplace_back(type.getType(), isMutable);
}
if (Node->getNumChildren() > 1) {
auto *substNode = Node->getChild(2);
if (substNode->getKind() != NodeKind::TypeList)
return MAKE_NODE_TYPE_ERROR0(substNode, "expected type list");
auto *dependentGenericSignatureNode = Node->getChild(1);
if (dependentGenericSignatureNode->getKind() !=
NodeKind::DependentGenericSignature)
return MAKE_NODE_TYPE_ERROR0(dependentGenericSignatureNode,
"expected dependent generic signature");
if (dependentGenericSignatureNode->getNumChildren() < 1)
return MAKE_NODE_TYPE_ERROR(
dependentGenericSignatureNode,
"fewer children (%zu) than required (1)",
dependentGenericSignatureNode->getNumChildren());
decodeRequirement<BuiltType, BuiltRequirement, BuiltLayoutConstraint,
BuilderType>(dependentGenericSignatureNode,
requirements,
Builder /*,
[&](NodePointer Node) -> BuiltType {
return decodeMangledType(Node, depth + 1).getType();
},
[&](LayoutConstraintKind Kind) -> BuiltLayoutConstraint {
return {}; // Not implemented!
},
[&](LayoutConstraintKind Kind, unsigned SizeInBits,
unsigned Alignment) -> BuiltLayoutConstraint {
return {}; // Not Implemented!
}*/);
// The number of generic parameters at each depth are in a mini
// state machine and come first.
llvm::SmallVector<unsigned, 4> genericParamsAtDepth;
for (auto *reqNode : *dependentGenericSignatureNode)
if (reqNode->getKind() == NodeKind::DependentGenericParamCount)
if (reqNode->hasIndex())
genericParamsAtDepth.push_back(reqNode->getIndex());
unsigned paramDepth = 0;
unsigned index = 0;
for (auto *subst : *substNode) {
if (paramDepth >= genericParamsAtDepth.size())
return MAKE_NODE_TYPE_ERROR0(
dependentGenericSignatureNode,
"more substitutions than generic params");
while (index >= genericParamsAtDepth[paramDepth])
++paramDepth, index = 0;
auto substTy = decodeMangledType(subst, depth + 1,
/*forRequirement=*/false);
if (substTy.isError())
return substTy;
substitutions.emplace_back(
Builder.createGenericTypeParameterType(paramDepth, index),
substTy.getType());
++index;
}
}
return Builder.createSILBoxTypeWithLayout(fields, substitutions,
requirements);
}
case NodeKind::SugaredOptional: {
if (Node->getNumChildren() < 1)
return MAKE_NODE_TYPE_ERROR0(Node, "no children");
auto base = decodeMangledType(Node->getChild(0), depth + 1);
if (base.isError())
return base;
return Builder.createOptionalType(base.getType());
}
case NodeKind::SugaredArray: {
if (Node->getNumChildren() < 1)
return MAKE_NODE_TYPE_ERROR0(Node, "no children");
auto base = decodeMangledType(Node->getChild(0), depth + 1);
if (base.isError())
return base;
return Builder.createArrayType(base.getType());
}
case NodeKind::SugaredDictionary: {
if (Node->getNumChildren() < 2)
return MAKE_NODE_TYPE_ERROR(Node,
"fewer children (%zu) than required (2)",
Node->getNumChildren());
auto key = decodeMangledType(Node->getChild(0), depth + 1);
if (key.isError())
return key;
auto value = decodeMangledType(Node->getChild(1), depth + 1);
if (value.isError())
return value;
return Builder.createDictionaryType(key.getType(), value.getType());
}
case NodeKind::SugaredParen: {
if (Node->getNumChildren() < 1)
return MAKE_NODE_TYPE_ERROR0(Node, "no children");
auto base = decodeMangledType(Node->getChild(0), depth + 1);
if (base.isError())
return base;
return Builder.createParenType(base.getType());
}
case NodeKind::OpaqueType: {
if (Node->getNumChildren() < 3)
return MAKE_NODE_TYPE_ERROR(Node,
"fewer children (%zu) than required (3)",
Node->getNumChildren());
auto descriptor = Node->getChild(0);
auto ordinalNode = Node->getChild(1);
if (ordinalNode->getKind() != NodeKind::Index
|| !ordinalNode->hasIndex())
return MAKE_NODE_TYPE_ERROR0(ordinalNode,
"unexpected kind or no index");
auto ordinal = ordinalNode->getIndex();
std::vector<BuiltType> genericArgsBuf;
std::vector<unsigned> genericArgsLevels;
auto boundGenerics = Node->getChild(2);
for (unsigned i = 0; i < boundGenerics->getNumChildren(); ++i) {
genericArgsLevels.push_back(genericArgsBuf.size());
auto genericsNode = boundGenerics->getChild(i);
if (genericsNode->getKind() != NodeKind::TypeList)
break;
for (auto argNode : *genericsNode) {
auto arg = decodeMangledType(argNode, depth + 1,
/*forRequirement=*/false);
if (arg.isError())
return arg;
genericArgsBuf.push_back(arg.getType());
}
}
genericArgsLevels.push_back(genericArgsBuf.size());
std::vector<llvm::ArrayRef<BuiltType>> genericArgs;
for (unsigned i = 0; i < genericArgsLevels.size() - 1; ++i) {
auto start = genericArgsLevels[i], end = genericArgsLevels[i+1];
genericArgs.emplace_back(genericArgsBuf.data() + start,
end - start);
}
return Builder.resolveOpaqueType(descriptor, genericArgs, ordinal);
}
// TODO: Handle OpaqueReturnType, when we're in the middle of reconstructing
// the defining decl
default:
return MAKE_NODE_TYPE_ERROR0(Node, "unexpected kind");
}
}