mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
If the specialized function has a re-abstracted (= converted from indirect to direct) resilient argument or return types, use an alternative mangling: "TB" instead of "Tg". Resilient parameters/returns can be converted from indirect to direct if the specialization is created within the type's resilience domain, i.e. in its module (where the type is loadable). In this case we need to generate a different mangled name for the specialized function to distinguish it from specializations in other modules, which cannot re-abstract this resilient type. This fixes a miscompile resulting from ODR-linking specializations from different modules, which in fact have different function signatures. https://bugs.swift.org/browse/SR-13900 rdar://71914016
159 lines
5.3 KiB
C++
159 lines
5.3 KiB
C++
//===--- GenericSpecializationMangler.cpp - mangling of specializations ---===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/SIL/GenericSpecializationMangler.h"
|
|
#include "swift/AST/GenericEnvironment.h"
|
|
#include "swift/AST/GenericSignature.h"
|
|
#include "swift/AST/SubstitutionMap.h"
|
|
#include "swift/Demangling/ManglingMacros.h"
|
|
|
|
using namespace swift;
|
|
using namespace Mangle;
|
|
|
|
void SpecializationMangler::beginMangling() {
|
|
ASTMangler::beginManglingWithoutPrefix();
|
|
if (Serialized)
|
|
ArgOpBuffer << 'q';
|
|
ArgOpBuffer << char(uint8_t(Pass) + '0');
|
|
}
|
|
|
|
namespace {
|
|
|
|
/// Utility class for demangling specialization attributes.
|
|
class AttributeDemangler : public Demangle::Demangler {
|
|
public:
|
|
void demangleAndAddAsChildren(StringRef MangledSpecialization,
|
|
NodePointer Parent) {
|
|
DemangleInitRAII state(*this, MangledSpecialization, nullptr);
|
|
if (!parseAndPushNodes()) {
|
|
llvm::errs() << "Can't demangle: " << MangledSpecialization << '\n';
|
|
abort();
|
|
}
|
|
for (Node *Nd : NodeStack) {
|
|
addChild(Parent, Nd);
|
|
}
|
|
}
|
|
};
|
|
|
|
} // namespace
|
|
|
|
std::string SpecializationMangler::finalize() {
|
|
StringRef MangledSpecialization(Storage.data(), Storage.size());
|
|
AttributeDemangler D;
|
|
NodePointer TopLevel = D.createNode(Node::Kind::Global);
|
|
D.demangleAndAddAsChildren(MangledSpecialization, TopLevel);
|
|
|
|
StringRef FuncName = Function ? Function->getName() : StringRef(FunctionName);
|
|
NodePointer FuncTopLevel = nullptr;
|
|
if (FuncName.startswith(MANGLING_PREFIX_STR)) {
|
|
FuncTopLevel = D.demangleSymbol(FuncName);
|
|
assert(FuncTopLevel);
|
|
}
|
|
if (!FuncTopLevel) {
|
|
FuncTopLevel = D.createNode(Node::Kind::Global);
|
|
FuncTopLevel->addChild(D.createNode(Node::Kind::Identifier, FuncName), D);
|
|
}
|
|
for (NodePointer FuncChild : *FuncTopLevel) {
|
|
TopLevel->addChild(FuncChild, D);
|
|
}
|
|
std::string mangledName = Demangle::mangleNode(TopLevel);
|
|
verify(mangledName);
|
|
return mangledName;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Generic Specialization
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
void GenericSpecializationMangler::
|
|
appendSubstitutions(GenericSignature sig, SubstitutionMap subs) {
|
|
bool First = true;
|
|
sig->forEachParam([&](GenericTypeParamType *ParamType, bool Canonical) {
|
|
if (Canonical) {
|
|
appendType(Type(ParamType).subst(subs)->getCanonicalType());
|
|
appendListSeparator(First);
|
|
}
|
|
});
|
|
assert(!First && "no generic substitutions");
|
|
}
|
|
|
|
std::string GenericSpecializationMangler::
|
|
manglePrespecialized(GenericSignature sig, SubstitutionMap subs) {
|
|
beginMangling();
|
|
appendSubstitutions(sig, subs);
|
|
appendSpecializationOperator("Ts");
|
|
return finalize();
|
|
}
|
|
|
|
std::string GenericSpecializationMangler::
|
|
mangleNotReabstracted(SubstitutionMap subs) {
|
|
beginMangling();
|
|
appendSubstitutions(getGenericSignature(), subs);
|
|
appendSpecializationOperator("TG");
|
|
return finalize();
|
|
}
|
|
|
|
std::string GenericSpecializationMangler::
|
|
mangleReabstracted(SubstitutionMap subs, bool alternativeMangling) {
|
|
beginMangling();
|
|
appendSubstitutions(getGenericSignature(), subs);
|
|
|
|
// See ReabstractionInfo::hasConvertedResilientParams for why and when to use
|
|
// the alternative mangling.
|
|
appendSpecializationOperator(alternativeMangling ? "TB" : "Tg");
|
|
return finalize();
|
|
}
|
|
|
|
std::string GenericSpecializationMangler::
|
|
mangleForDebugInfo(GenericSignature sig, SubstitutionMap subs, bool forInlining) {
|
|
beginMangling();
|
|
appendSubstitutions(sig, subs);
|
|
appendSpecializationOperator(forInlining ? "Ti" : "TG");
|
|
return finalize();
|
|
}
|
|
|
|
|
|
static SubstitutionMap
|
|
getSubstitutionMapForPrespecialization(GenericSignature genericSig,
|
|
GenericSignature specSig) {
|
|
auto CalleeGenericSig = genericSig;
|
|
auto SpecializedGenericSig = specSig;
|
|
auto SpecializedGenericEnv = specSig->getGenericEnvironment();
|
|
|
|
auto CalleeInterfaceToSpecializedInterfaceMap = SubstitutionMap::get(
|
|
CalleeGenericSig,
|
|
[&](SubstitutableType *type) -> Type {
|
|
return type;
|
|
},
|
|
LookUpConformanceInSignature(CalleeGenericSig.getPointer()));
|
|
|
|
auto subs = SubstitutionMap::get(
|
|
CalleeGenericSig,
|
|
[&](SubstitutableType *type) -> Type {
|
|
auto SpecializedInterfaceTy =
|
|
Type(type).subst(CalleeInterfaceToSpecializedInterfaceMap);
|
|
return SpecializedGenericEnv->mapTypeIntoContext(
|
|
SpecializedInterfaceTy);
|
|
},
|
|
LookUpConformanceInSignature(SpecializedGenericSig.getPointer()));
|
|
return subs;
|
|
}
|
|
|
|
std::string GenericSpecializationMangler::manglePrespecialization(
|
|
std::string unspecializedName, GenericSignature genericSig,
|
|
GenericSignature specializedSig) {
|
|
auto subs =
|
|
getSubstitutionMapForPrespecialization(genericSig, specializedSig);
|
|
GenericSpecializationMangler mangler(unspecializedName);
|
|
return mangler.manglePrespecialized(genericSig, subs);
|
|
}
|