//===--- 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/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) { init(MangledSpecialization); 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->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) { 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 SILInstructionKind::FunctionRefInst: { SILFunction *F = cast(LI)->getReferencedFunction(); ArgOpBuffer << 'f'; appendIdentifier(F->getName()); break; } case SILInstructionKind::GlobalAddrInst: { SILGlobalVariable *G = cast(LI)->getReferencedGlobal(); ArgOpBuffer << 'g'; appendIdentifier(G->getName()); break; } case SILInstructionKind::IntegerLiteralInst: { APInt apint = cast(LI)->getValue(); ArgOpBuffer << 'i' << apint; break; } case SILInstructionKind::FloatLiteralInst: { APInt apint = cast(LI)->getBits(); ArgOpBuffer << 'd' << apint; break; } case SILInstructionKind::StringLiteralInst: { StringLiteralInst *SLI = cast(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(Inst)) { auto *FRI = cast(TTTFI->getCallee()); appendIdentifier(FRI->getReferencedFunction()->getName()); return; } auto *PAI = cast(Inst); auto *FRI = cast(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 Inst) { if (ArgMod == ArgumentModifierIntBase(ArgumentModifier::ConstantProp)) { mangleConstantProp(cast(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 Inst; std::tie(ArgMod, Inst) = OrigArgs[i]; mangleArgument(ArgMod, Inst); } ArgOpBuffer << '_'; mangleReturnValue(ReturnValue); appendSpecializationOperator("Tf"); return finalize(); }