diff --git a/docs/ABI.rst b/docs/ABI.rst index 6da45480702..dcf300316aa 100644 --- a/docs/ABI.rst +++ b/docs/ABI.rst @@ -998,13 +998,17 @@ Types type ::= type 'Xu' // @unowned(unsafe) type type ::= type 'Xw' // @weak type type ::= impl-function-type 'XF' // function implementation type (currently unused) - type ::= type 'Xb' // SIL @box type + type ::= type 'Xb' // SIL @box type (deprecated) + type ::= type-list 'Xx' // SIL box type + type ::= type-list type-list generic-signature 'XX' + // Generic SIL box type type ::= type 'XD' // dynamic self type type ::= type 'm' // metatype without representation type ::= type 'XM' METATYPE-REPR // metatype with representation type ::= type 'Xp' // existential metatype without representation type ::= type 'Xm' METATYPE-REPR // existential metatype with representation + FUNCTION-KIND ::= 'f' // @thin function type FUNCTION-KIND ::= 'U' // uncurried function type (currently not used) FUNCTION-KIND ::= 'K' // @auto_closure function type diff --git a/include/swift/AST/Mangle.h b/include/swift/AST/Mangle.h index 7b0fa0a3e89..60d907ccf51 100644 --- a/include/swift/AST/Mangle.h +++ b/include/swift/AST/Mangle.h @@ -95,6 +95,7 @@ public: void mangleBoundGenericType(Type type); void mangleProtocolDecl(const ProtocolDecl *protocol); void mangleType(Type type, unsigned uncurryingLevel); + void mangleLegacyBoxType(CanType fieldType); void mangleDirectness(bool isIndirect); void mangleProtocolName(const ProtocolDecl *protocol); void mangleProtocolConformance(const ProtocolConformance *conformance); diff --git a/include/swift/Basic/DemangleNodes.def b/include/swift/Basic/DemangleNodes.def index e0d4cf13783..c7e75f5d1f8 100644 --- a/include/swift/Basic/DemangleNodes.def +++ b/include/swift/Basic/DemangleNodes.def @@ -131,6 +131,10 @@ NODE(ReabstractionThunk) NODE(ReabstractionThunkHelper) NODE(ReturnType) NODE(SILBoxType) +NODE(SILBoxTypeWithLayout) +NODE(SILBoxLayout) +NODE(SILBoxMutableField) +NODE(SILBoxImmutableField) CONTEXT_NODE(Setter) NODE(SpecializationPassID) NODE(SpecializationIsFragile) diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h index 4d381cffd0b..f6c39276b29 100644 --- a/include/swift/Remote/MetadataReader.h +++ b/include/swift/Remote/MetadataReader.h @@ -313,6 +313,11 @@ class TypeDecoder { return BuiltType(); return Builder.createSILBoxType(base); } + case NodeKind::SILBoxTypeWithLayout: { + // TODO: Implement SILBoxTypeRefs with layout. As a stopgap, specify the + // NativeObject type ref. + return Builder.createBuiltinType("Bo"); + } default: return BuiltType(); } diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp index 7e7ee066462..71e93289e1d 100644 --- a/lib/AST/ASTMangler.cpp +++ b/lib/AST/ASTMangler.cpp @@ -657,9 +657,35 @@ void ASTMangler::appendType(Type type) { appendFunctionType(cast(tybase)); return; - case TypeKind::SILBox: - appendType(cast(tybase)->getBoxedType()); - return appendOperator("Xb"); + case TypeKind::SILBox: { + auto box = cast(tybase); + auto layout = box->getLayout(); + SmallVector fieldsList; + for (auto &field : layout->getFields()) { + auto fieldTy = field.getLoweredType(); + // Use the `inout` mangling to represent a mutable field. + if (field.isMutable()) + fieldTy = CanInOutType::get(fieldTy); + fieldsList.push_back(TupleTypeElt(fieldTy)); + } + appendTypeList(TupleType::get(fieldsList, tybase->getASTContext()) + ->getCanonicalType()); + + if (auto sig = layout->getGenericSignature()) { + fieldsList.clear(); + for (auto &arg : box->getGenericArgs()) { + fieldsList.push_back(TupleTypeElt(arg.getReplacement())); + } + appendTypeList(TupleType::get(fieldsList, tybase->getASTContext()) + ->getCanonicalType()); + appendGenericSignature(sig); + appendOperator("XX"); + } else { + appendOperator("Xx"); + } + + return; + } case TypeKind::SILBlockStorage: llvm_unreachable("should never be mangled"); diff --git a/lib/AST/Mangle.cpp b/lib/AST/Mangle.cpp index c77cd4ecbb0..f711573b641 100644 --- a/lib/AST/Mangle.cpp +++ b/lib/AST/Mangle.cpp @@ -1217,11 +1217,28 @@ void Mangler::mangleType(Type type, unsigned uncurryLevel) { return; } - case TypeKind::SILBox: - Buffer << 'X' << 'b'; - mangleType(cast(tybase)->getBoxedType(), - uncurryLevel); + case TypeKind::SILBox: { + Buffer << 'X' << 'B'; + auto boxTy = cast(tybase); + // TODO: Should layouts get substitutions? + auto layout = boxTy->getLayout(); + if (auto sig = layout->getGenericSignature()) { + Buffer << 'G'; + mangleGenericSignature(sig); + } + for (auto &field : layout->getFields()) { + Buffer << (field.isMutable() ? 'm' : 'i'); + mangleType(field.getLoweredType(), 0); + } + Buffer << '_'; + if (!boxTy->getGenericArgs().empty()) { + for (auto &arg : boxTy->getGenericArgs()) { + mangleType(arg.getReplacement(), 0); + } + Buffer << '_'; + } return; + } case TypeKind::SILBlockStorage: llvm_unreachable("should never be mangled"); @@ -1229,6 +1246,11 @@ void Mangler::mangleType(Type type, unsigned uncurryLevel) { llvm_unreachable("bad type kind"); } +void Mangler::mangleLegacyBoxType(CanType fieldType) { + Buffer << 'X' << 'b'; + mangleType(fieldType, 0); +} + /// Mangle a list of protocols. Each protocol is a substitution /// candidate. /// ::= + diff --git a/lib/Basic/Demangle.cpp b/lib/Basic/Demangle.cpp index 4d446d29d05..e701efa2426 100644 --- a/lib/Basic/Demangle.cpp +++ b/lib/Basic/Demangle.cpp @@ -1921,6 +1921,50 @@ private: boxType->addChild(type); return boxType; } + if (Mangled.nextIf('B')) { + NodePointer signature; + if (Mangled.nextIf('G')) { + signature = demangleGenericSignature(/*pseudogeneric*/ false); + if (!signature) + return nullptr; + } + NodePointer layout = NodeFactory::create(Node::Kind::SILBoxLayout); + while (!Mangled.nextIf('_')) { + Node::Kind kind; + if (Mangled.nextIf('m')) + kind = Node::Kind::SILBoxMutableField; + else if (Mangled.nextIf('i')) + kind = Node::Kind::SILBoxImmutableField; + else + return nullptr; + + auto type = demangleType(); + if (!type) + return nullptr; + auto field = NodeFactory::create(kind); + field->addChild(type); + layout->addChild(field); + } + NodePointer genericArgs; + if (signature) { + genericArgs = NodeFactory::create(Node::Kind::TypeList); + while (!Mangled.nextIf('_')) { + auto type = demangleType(); + if (!type) + return nullptr; + genericArgs->addChild(type); + } + } + NodePointer boxType = + NodeFactory::create(Node::Kind::SILBoxTypeWithLayout); + boxType->addChild(layout); + if (signature) { + boxType->addChild(signature); + assert(genericArgs); + boxType->addChild(genericArgs); + } + return boxType; + } } if (c == 'K') { return demangleFunctionType(Node::Kind::AutoClosureType); @@ -2365,6 +2409,7 @@ private: case Node::Kind::QualifiedArchetype: case Node::Kind::ReturnType: case Node::Kind::SILBoxType: + case Node::Kind::SILBoxTypeWithLayout: case Node::Kind::Structure: case Node::Kind::TupleElementName: case Node::Kind::Type: @@ -2462,6 +2507,9 @@ private: case Node::Kind::ReabstractionThunk: case Node::Kind::ReabstractionThunkHelper: case Node::Kind::Setter: + case Node::Kind::SILBoxLayout: + case Node::Kind::SILBoxMutableField: + case Node::Kind::SILBoxImmutableField: case Node::Kind::SpecializationIsFragile: case Node::Kind::SpecializationPassID: case Node::Kind::Static: @@ -3690,6 +3738,51 @@ void NodePrinter::print(NodePointer pointer, bool asContext, bool suppressType) case Node::Kind::VariadicMarker: Printer << " variadic-marker "; return; + case Node::Kind::SILBoxTypeWithLayout: { + assert(pointer->getNumChildren() == 1 || pointer->getNumChildren() == 3); + NodePointer layout = pointer->getChild(0); + assert(layout->getKind() == Node::Kind::SILBoxLayout); + NodePointer signature, genericArgs; + if (pointer->getNumChildren() == 3) { + signature = pointer->getChild(1); + assert(signature->getKind() == Node::Kind::DependentGenericSignature); + genericArgs = pointer->getChild(2); + assert(signature->getKind() == Node::Kind::TypeList); + + print(signature); + Printer << ' '; + } + print(layout); + if (genericArgs) { + Printer << " <"; + for (unsigned i = 0, e = genericArgs->getNumChildren(); i < e; ++i) { + if (i > 0) + Printer << ", "; + print(genericArgs->getChild(i)); + } + Printer << '>'; + } + return; + } + case Node::Kind::SILBoxLayout: + Printer << '{'; + for (unsigned i = 0; i < pointer->getNumChildren(); ++i) { + if (i > 0) + Printer << ','; + Printer << ' '; + print(pointer->getChild(i)); + } + Printer << " }"; + return; + case Node::Kind::SILBoxImmutableField: + case Node::Kind::SILBoxMutableField: + Printer << (pointer->getKind() == Node::Kind::SILBoxImmutableField + ? "let " + : "var "); + assert(pointer->getNumChildren() == 1 + && pointer->getChild(0)->getKind() == Node::Kind::Type); + print(pointer->getChild(0)); + return; } unreachable("bad node kind!"); } diff --git a/lib/Basic/Demangler.cpp b/lib/Basic/Demangler.cpp index 72dbeb8256a..f98cc0d992a 100644 --- a/lib/Basic/Demangler.cpp +++ b/lib/Basic/Demangler.cpp @@ -1253,7 +1253,7 @@ NodePointer Demangler::demangleWitness() { } NodePointer Demangler::demangleSpecialType() { - switch (nextChar()) { + switch (auto specialChar = nextChar()) { case 'f': return popFunctionType(Node::Kind::ThinFunctionType); case 'K': @@ -1293,6 +1293,48 @@ NodePointer Demangler::demangleSpecialType() { case 'p': return createType(createWithChild(Node::Kind::ExistentialMetatype, popNode(Node::Kind::Type))); + case 'X': + case 'x': { + // SIL box types. + NodePointer signature, genericArgs; + if (specialChar == 'X') { + signature = popNode(Node::Kind::DependentGenericSignature); + if (!signature) + return nullptr; + genericArgs = popTypeList(); + if (!genericArgs) + return nullptr; + } + + auto fieldTypes = popTypeList(); + if (!fieldTypes) + return nullptr; + // Build layout. + auto layout = NodeFactory::create(Node::Kind::SILBoxLayout); + for (unsigned i = 0, e = fieldTypes->getNumChildren(); i < e; ++i) { + auto fieldType = fieldTypes->getChild(i); + assert(fieldType->getKind() == Node::Kind::Type); + bool isMutable = false; + // 'inout' typelist mangling is used to represent mutable fields. + if (fieldType->getChild(0)->getKind() == Node::Kind::InOut) { + isMutable = true; + fieldType = createType(fieldType->getChild(0)->getChild(0)); + } + auto field = NodeFactory::create(isMutable + ? Node::Kind::SILBoxMutableField + : Node::Kind::SILBoxImmutableField); + field->addChild(fieldType); + layout->addChild(field); + } + auto boxTy = NodeFactory::create(Node::Kind::SILBoxTypeWithLayout); + boxTy->addChild(layout); + if (signature) { + boxTy->addChild(signature); + assert(genericArgs); + boxTy->addChild(genericArgs); + } + return createType(boxTy); + } default: return nullptr; } diff --git a/lib/Basic/Remangle.cpp b/lib/Basic/Remangle.cpp index c21e0477418..4d4617ef59c 100644 --- a/lib/Basic/Remangle.cpp +++ b/lib/Basic/Remangle.cpp @@ -1684,6 +1684,59 @@ void Remangler::mangleVariadicMarker(Node *node) { Out << ""; } +void Remangler::mangleSILBoxTypeWithLayout(Node *node) { + assert(node->getKind() == Node::Kind::SILBoxTypeWithLayout); + assert(node->getNumChildren() == 1 || node->getNumChildren() == 3); + Out << "XB"; + auto layout = node->getChild(0); + assert(layout->getKind() == Node::Kind::SILBoxLayout); + NodePointer signature, genericArgs; + if (node->getNumChildren() == 3) { + signature = node->getChild(1); + assert(signature->getKind() == Node::Kind::DependentGenericSignature); + genericArgs = node->getChild(2); + assert(genericArgs->getKind() == Node::Kind::TypeList); + + Out << 'G'; + mangleDependentGenericSignature(signature.get()); + } + mangleSILBoxLayout(layout.get()); + if (genericArgs) { + for (unsigned i = 0; i < genericArgs->getNumChildren(); ++i) { + auto type = genericArgs->getChild(i); + assert(genericArgs->getKind() == Node::Kind::Type); + mangleType(type.get()); + } + Out << '_'; + } +} + +void Remangler::mangleSILBoxLayout(Node *node) { + assert(node->getKind() == Node::Kind::SILBoxLayout); + for (unsigned i = 0; i < node->getNumChildren(); ++i) { + auto field = node->getChild(i); + assert(node->getKind() == Node::Kind::SILBoxImmutableField + || node->getKind() == Node::Kind::SILBoxMutableField); + mangle(node->getChild(i).get()); + + } + Out << '_'; +} + +void Remangler::mangleSILBoxMutableField(Node *node) { + Out << 'm'; + assert(node->getNumChildren() == 1 + && node->getChild(0)->getKind() == Node::Kind::Type); + mangleType(node->getChild(0).get()); +} + +void Remangler::mangleSILBoxImmutableField(Node *node) { + Out << 'i'; + assert(node->getNumChildren() == 1 + && node->getChild(0)->getKind() == Node::Kind::Type); + mangleType(node->getChild(0).get()); +} + /// The top-level interface to the remangler. std::string Demangle::mangleNode(const NodePointer &node) { if (!node) return ""; diff --git a/lib/Basic/Remangler.cpp b/lib/Basic/Remangler.cpp index 979d9c3f224..43501822334 100644 --- a/lib/Basic/Remangler.cpp +++ b/lib/Basic/Remangler.cpp @@ -1579,6 +1579,54 @@ void Remangler::mangleVariadicMarker(Node *node) { Buffer << 'd'; } +void Remangler::mangleSILBoxTypeWithLayout(Node *node) { + assert(node->getNumChildren() == 1 || node->getNumChildren() == 3); + assert(node->getChild(0)->getKind() == Node::Kind::SILBoxLayout); + auto layout = node->getChild(0); + auto layoutTypeList = NodeFactory::create(Node::Kind::TypeList); + for (unsigned i = 0, e = layout->getNumChildren(); i < e; ++i) { + assert(layout->getChild(i)->getKind() == Node::Kind::SILBoxImmutableField + || layout->getChild(i)->getKind() == Node::Kind::SILBoxMutableField); + auto field = layout->getChild(i); + assert(field->getNumChildren() == 1 + && field->getChild(0)->getKind() == Node::Kind::Type); + auto fieldType = field->getChild(0); + // 'inout' mangling is used to represent mutable fields. + if (field->getKind() == Node::Kind::SILBoxMutableField) { + auto inout = NodeFactory::create(Node::Kind::InOut); + inout->addChild(fieldType->getChild(0)); + fieldType = NodeFactory::create(Node::Kind::Type); + fieldType->addChild(inout); + } + layoutTypeList->addChild(fieldType); + } + mangleTypeList(layoutTypeList.get()); + + if (node->getNumChildren() == 3) { + auto signature = node->getChild(1); + auto genericArgs = node->getChild(2); + assert(signature->getKind() == Node::Kind::DependentGenericSignature); + assert(genericArgs->getKind() == Node::Kind::TypeList); + mangleTypeList(genericArgs.get()); + mangleDependentGenericSignature(signature.get()); + Buffer << "XX"; + } else { + Buffer << "Xx"; + } +} + +void Remangler::mangleSILBoxLayout(Node *node) { + unreachable("should be part of SILBoxTypeWithLayout"); +} + +void Remangler::mangleSILBoxMutableField(Node *node) { + unreachable("should be part of SILBoxTypeWithLayout"); +} + +void Remangler::mangleSILBoxImmutableField(Node *node) { + unreachable("should be part of SILBoxTypeWithLayout"); +} + } // anonymous namespace /// The top-level interface to the remangler. diff --git a/lib/IRGen/GenHeap.cpp b/lib/IRGen/GenHeap.cpp index 35c4d140c77..f3e278807bd 100644 --- a/lib/IRGen/GenHeap.cpp +++ b/lib/IRGen/GenHeap.cpp @@ -1551,7 +1551,10 @@ public: const TypeInfo *TypeConverter::convertBoxType(SILBoxType *T) { // We can share a type info for all dynamic-sized heap metadata. - auto &eltTI = IGM.getTypeInfoForLowered(T->getBoxedType()); + // TODO: Multi-field boxes + assert(T->getLayout()->getFields().size() == 1 + && "multi-field boxes not implemented yet"); + auto &eltTI = IGM.getTypeInfoForLowered(T->getFieldLoweredType(0)); if (!eltTI.isFixedSize()) { if (!NonFixedBoxTI) NonFixedBoxTI = new NonFixedBoxTypeInfo(IGM); diff --git a/lib/IRGen/GenReflection.cpp b/lib/IRGen/GenReflection.cpp index 7b3e17a9f2d..f1f643a0e2c 100644 --- a/lib/IRGen/GenReflection.cpp +++ b/lib/IRGen/GenReflection.cpp @@ -216,7 +216,15 @@ protected: /*usePunyCode*/ true, /*OptimizeProtocolNames*/ false); mangler.setModuleContext(ModuleContext); - mangler.mangleType(type, 0); + + // TODO: As a compatibility hack, mangle single-field boxes with the legacy + // mangling in reflection metadata. + auto boxTy = dyn_cast(type); + if (boxTy && boxTy->getLayout()->getFields().size() == 1) { + mangler.mangleLegacyBoxType(boxTy->getFieldLoweredType(0)); + } else { + mangler.mangleType(type, 0); + } auto mangledName = IGM.getAddrOfStringForTypeRef(mangler.finalize()); addRelativeAddress(mangledName); } diff --git a/test/SILOptimizer/closure_specialize.sil b/test/SILOptimizer/closure_specialize.sil index 65695f4c8f1..94e3acfb816 100644 --- a/test/SILOptimizer/closure_specialize.sil +++ b/test/SILOptimizer/closure_specialize.sil @@ -424,7 +424,7 @@ bb4: // Ensure that we can specialize and properly mangle functions that take closures with <τ_0_0> { var τ_0_0 } . -// CHECK-LABEL: sil shared [noinline] @_TTSf1n_cl25closure_with_box_argumentXbBi32____TF4main5innerFTRVs5Int32FS0_T__T_ : $@convention(thin) (@inout Builtin.Int32, @owned <τ_0_0> { var τ_0_0 } ) -> () +// CHECK-LABEL: sil shared [noinline] @_TTSf1n_cl25closure_with_box_argumentXBGrmx_Bi32_____TF4main5innerFTRVs5Int32FS0_T__T_ : $@convention(thin) (@inout Builtin.Int32, @owned <τ_0_0> { var τ_0_0 } ) -> () // CHECK: bb0 // CHECK: [[FN:%.*]] = function_ref @closure_with_box_argument // CHECK: [[PARTIAL:%.*]] = partial_apply [[FN]](%1)