mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Also, add a third [serializable] state for functions whose bodies we *can* serialize, but only do so if they're referenced from another serialized function. This will be used for bodies synthesized for imported definitions, such as init(rawValue:), etc, and various thunks, but for now this change is NFC.
319 lines
10 KiB
C++
319 lines
10 KiB
C++
//===--- SpecializationMangler.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/SILOptimizer/Utils/SpecializationMangler.h"
|
|
#include "swift/SIL/SILGlobalVariable.h"
|
|
#include "swift/AST/SubstitutionMap.h"
|
|
#include "swift/Demangling/ManglingMacros.h"
|
|
|
|
using namespace swift;
|
|
using namespace Mangle;
|
|
|
|
void SpecializationMangler::beginMangling() {
|
|
ASTMangler::beginMangling();
|
|
if (Serialized)
|
|
ArgOpBuffer << 'q';
|
|
ArgOpBuffer << char(uint8_t(Pass) + '0');
|
|
}
|
|
|
|
std::string SpecializationMangler::finalize() {
|
|
StringRef MangledSpecialization(Storage.data(), Storage.size());
|
|
Demangle::Demangler D;
|
|
NodePointer TopLevel = D.demangleSymbol(MangledSpecialization);
|
|
|
|
StringRef FuncName = Function->getName();
|
|
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) {
|
|
assert(FuncChild->getKind() != Node::Kind::Suffix ||
|
|
FuncChild->getText() == "merged");
|
|
TopLevel->addChild(FuncChild, D);
|
|
}
|
|
std::string mangledName = Demangle::mangleNode(TopLevel);
|
|
verify(mangledName);
|
|
return mangledName;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Generic Specialization
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
std::string GenericSpecializationMangler::mangle() {
|
|
beginMangling();
|
|
|
|
SILFunctionType *FTy = Function->getLoweredFunctionType();
|
|
CanGenericSignature Sig = FTy->getGenericSignature();
|
|
|
|
auto SubMap = Sig->getSubstitutionMap(Subs);
|
|
bool First = true;
|
|
for (auto ParamType : Sig->getSubstitutableParams()) {
|
|
appendType(Type(ParamType).subst(SubMap)->getCanonicalType());
|
|
appendListSeparator(First);
|
|
}
|
|
assert(!First && "no generic substitutions");
|
|
|
|
appendSpecializationOperator(isReAbstracted ? "Tg" : "TG");
|
|
return finalize();
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Partial Generic Specialization
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
std::string PartialSpecializationMangler::mangle() {
|
|
beginMangling();
|
|
appendType(SpecializedFnTy);
|
|
appendSpecializationOperator(isReAbstracted ? "Tp" : "TP");
|
|
return finalize();
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Function Signature Optimizations
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
FunctionSignatureSpecializationMangler::
|
|
FunctionSignatureSpecializationMangler(Demangle::SpecializationPass P,
|
|
IsSerialized_t Serialized, SILFunction *F)
|
|
: SpecializationMangler(P, Serialized, F) {
|
|
for (unsigned i = 0, e = F->getConventions().getNumSILArguments(); i != e;
|
|
++i) {
|
|
(void)i;
|
|
OrigArgs.push_back(
|
|
{ArgumentModifierIntBase(ArgumentModifier::Unmodified), nullptr});
|
|
}
|
|
ReturnValue = ReturnValueModifierIntBase(ReturnValueModifier::Unmodified);
|
|
}
|
|
|
|
void FunctionSignatureSpecializationMangler::setArgumentDead(
|
|
unsigned OrigArgIdx) {
|
|
OrigArgs[OrigArgIdx].first |= ArgumentModifierIntBase(ArgumentModifier::Dead);
|
|
}
|
|
|
|
void FunctionSignatureSpecializationMangler::setArgumentClosureProp(
|
|
unsigned OrigArgIdx, PartialApplyInst *PAI) {
|
|
auto &Info = OrigArgs[OrigArgIdx];
|
|
Info.first = ArgumentModifierIntBase(ArgumentModifier::ClosureProp);
|
|
Info.second = PAI;
|
|
}
|
|
|
|
void FunctionSignatureSpecializationMangler::setArgumentClosureProp(
|
|
unsigned OrigArgIdx, ThinToThickFunctionInst *TTTFI) {
|
|
auto &Info = OrigArgs[OrigArgIdx];
|
|
Info.first = ArgumentModifierIntBase(ArgumentModifier::ClosureProp);
|
|
Info.second = TTTFI;
|
|
}
|
|
|
|
void FunctionSignatureSpecializationMangler::setArgumentConstantProp(
|
|
unsigned OrigArgIdx, LiteralInst *LI) {
|
|
auto &Info = OrigArgs[OrigArgIdx];
|
|
Info.first = ArgumentModifierIntBase(ArgumentModifier::ConstantProp);
|
|
Info.second = LI;
|
|
}
|
|
|
|
void FunctionSignatureSpecializationMangler::setArgumentOwnedToGuaranteed(
|
|
unsigned OrigArgIdx) {
|
|
OrigArgs[OrigArgIdx].first |=
|
|
ArgumentModifierIntBase(ArgumentModifier::OwnedToGuaranteed);
|
|
}
|
|
|
|
void FunctionSignatureSpecializationMangler::setArgumentSROA(
|
|
unsigned OrigArgIdx) {
|
|
OrigArgs[OrigArgIdx].first |= ArgumentModifierIntBase(ArgumentModifier::SROA);
|
|
}
|
|
|
|
void FunctionSignatureSpecializationMangler::setArgumentBoxToValue(
|
|
unsigned OrigArgIdx) {
|
|
OrigArgs[OrigArgIdx].first =
|
|
ArgumentModifierIntBase(ArgumentModifier::BoxToValue);
|
|
}
|
|
|
|
void FunctionSignatureSpecializationMangler::setArgumentBoxToStack(
|
|
unsigned OrigArgIdx) {
|
|
OrigArgs[OrigArgIdx].first =
|
|
ArgumentModifierIntBase(ArgumentModifier::BoxToStack);
|
|
}
|
|
|
|
void
|
|
FunctionSignatureSpecializationMangler::
|
|
setReturnValueOwnedToUnowned() {
|
|
ReturnValue |= ReturnValueModifierIntBase(ReturnValueModifier::OwnedToUnowned);
|
|
}
|
|
|
|
void
|
|
FunctionSignatureSpecializationMangler::mangleConstantProp(LiteralInst *LI) {
|
|
// Append the prefix for constant propagation 'p'.
|
|
ArgOpBuffer << 'p';
|
|
|
|
// Then append the unique identifier of our literal.
|
|
switch (LI->getKind()) {
|
|
default:
|
|
llvm_unreachable("unknown literal");
|
|
case ValueKind::FunctionRefInst: {
|
|
SILFunction *F = cast<FunctionRefInst>(LI)->getReferencedFunction();
|
|
ArgOpBuffer << 'f';
|
|
appendIdentifier(F->getName());
|
|
break;
|
|
}
|
|
case ValueKind::GlobalAddrInst: {
|
|
SILGlobalVariable *G = cast<GlobalAddrInst>(LI)->getReferencedGlobal();
|
|
ArgOpBuffer << 'g';
|
|
appendIdentifier(G->getName());
|
|
break;
|
|
}
|
|
case ValueKind::IntegerLiteralInst: {
|
|
APInt apint = cast<IntegerLiteralInst>(LI)->getValue();
|
|
ArgOpBuffer << 'i' << apint;
|
|
break;
|
|
}
|
|
case ValueKind::FloatLiteralInst: {
|
|
APInt apint = cast<FloatLiteralInst>(LI)->getBits();
|
|
ArgOpBuffer << 'd' << apint;
|
|
break;
|
|
}
|
|
case ValueKind::StringLiteralInst: {
|
|
StringLiteralInst *SLI = cast<StringLiteralInst>(LI);
|
|
StringRef V = SLI->getValue();
|
|
assert(V.size() <= 32 && "Cannot encode string of length > 32");
|
|
std::string VBuffer;
|
|
if (V.size() > 0 && (isDigit(V[0]) || V[0] == '_')) {
|
|
VBuffer = "_";
|
|
VBuffer.append(V.data(), V.size());
|
|
V = VBuffer;
|
|
}
|
|
appendIdentifier(V);
|
|
|
|
ArgOpBuffer << 's';
|
|
switch (SLI->getEncoding()) {
|
|
case StringLiteralInst::Encoding::UTF8: ArgOpBuffer << 'b'; break;
|
|
case StringLiteralInst::Encoding::UTF16: ArgOpBuffer << 'w'; break;
|
|
case StringLiteralInst::Encoding::ObjCSelector: ArgOpBuffer << 'c'; break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
FunctionSignatureSpecializationMangler::mangleClosureProp(SILInstruction *Inst) {
|
|
ArgOpBuffer << 'c';
|
|
|
|
// Add in the partial applies function name if we can find one. Assert
|
|
// otherwise. The reason why this is ok to do is currently we only perform
|
|
// closure specialization if we know the function_ref in question. When this
|
|
// restriction is removed, the assert here will fire.
|
|
if (auto *TTTFI = dyn_cast<ThinToThickFunctionInst>(Inst)) {
|
|
auto *FRI = cast<FunctionRefInst>(TTTFI->getCallee());
|
|
appendIdentifier(FRI->getReferencedFunction()->getName());
|
|
return;
|
|
}
|
|
auto *PAI = cast<PartialApplyInst>(Inst);
|
|
auto *FRI = cast<FunctionRefInst>(PAI->getCallee());
|
|
appendIdentifier(FRI->getReferencedFunction()->getName());
|
|
|
|
// Then we mangle the types of the arguments that the partial apply is
|
|
// specializing.
|
|
for (auto &Op : PAI->getArgumentOperands()) {
|
|
SILType Ty = Op.get()->getType();
|
|
appendType(Ty.getSwiftRValueType());
|
|
}
|
|
}
|
|
|
|
void FunctionSignatureSpecializationMangler::mangleArgument(
|
|
ArgumentModifierIntBase ArgMod, NullablePtr<SILInstruction> Inst) {
|
|
if (ArgMod == ArgumentModifierIntBase(ArgumentModifier::ConstantProp)) {
|
|
mangleConstantProp(cast<LiteralInst>(Inst.get()));
|
|
return;
|
|
}
|
|
|
|
if (ArgMod == ArgumentModifierIntBase(ArgumentModifier::ClosureProp)) {
|
|
mangleClosureProp(Inst.get());
|
|
return;
|
|
}
|
|
|
|
if (ArgMod == ArgumentModifierIntBase(ArgumentModifier::Unmodified)) {
|
|
ArgOpBuffer << 'n';
|
|
return;
|
|
}
|
|
|
|
if (ArgMod == ArgumentModifierIntBase(ArgumentModifier::BoxToValue)) {
|
|
ArgOpBuffer << 'i';
|
|
return;
|
|
}
|
|
|
|
if (ArgMod == ArgumentModifierIntBase(ArgumentModifier::BoxToStack)) {
|
|
ArgOpBuffer << 's';
|
|
return;
|
|
}
|
|
|
|
bool hasSomeMod = false;
|
|
if (ArgMod & ArgumentModifierIntBase(ArgumentModifier::Dead)) {
|
|
ArgOpBuffer << 'd';
|
|
hasSomeMod = true;
|
|
}
|
|
|
|
if (ArgMod & ArgumentModifierIntBase(ArgumentModifier::OwnedToGuaranteed)) {
|
|
ArgOpBuffer << (hasSomeMod ? 'G' : 'g');
|
|
hasSomeMod = true;
|
|
}
|
|
if (ArgMod & ArgumentModifierIntBase(ArgumentModifier::SROA)) {
|
|
ArgOpBuffer << (hasSomeMod ? 'X' : 'x');
|
|
hasSomeMod = true;
|
|
}
|
|
|
|
assert(hasSomeMod && "Unknown modifier");
|
|
}
|
|
|
|
void FunctionSignatureSpecializationMangler::
|
|
mangleReturnValue(ReturnValueModifierIntBase RetMod) {
|
|
if (RetMod == ReturnValueModifierIntBase(ReturnValueModifier::Unmodified)) {
|
|
ArgOpBuffer << 'n';
|
|
return;
|
|
}
|
|
|
|
bool hasSomeMode = false;
|
|
if (RetMod & ReturnValueModifierIntBase(ReturnValueModifier::Dead)) {
|
|
ArgOpBuffer << 'd';
|
|
hasSomeMode = true;
|
|
}
|
|
|
|
if (RetMod & ReturnValueModifierIntBase(ReturnValueModifier::OwnedToUnowned)) {
|
|
ArgOpBuffer << (hasSomeMode ? 'G' : 'g');
|
|
}
|
|
}
|
|
|
|
std::string FunctionSignatureSpecializationMangler::mangle(int UniqueID) {
|
|
ArgOpStorage.clear();
|
|
beginMangling();
|
|
|
|
if (UniqueID)
|
|
ArgOpBuffer << UniqueID;
|
|
|
|
for (unsigned i : indices(OrigArgs)) {
|
|
ArgumentModifierIntBase ArgMod;
|
|
NullablePtr<SILInstruction> Inst;
|
|
std::tie(ArgMod, Inst) = OrigArgs[i];
|
|
mangleArgument(ArgMod, Inst);
|
|
}
|
|
ArgOpBuffer << '_';
|
|
mangleReturnValue(ReturnValue);
|
|
|
|
appendSpecializationOperator("Tf");
|
|
return finalize();
|
|
}
|