| //===--- Mangle.cpp - SIL specific name Mangling --------------------------===// |
| // |
| // 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 |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements declaration specialized name mangling for SIL. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "swift/SIL/Mangle.h" |
| #include "swift/AST/ASTContext.h" |
| #include "swift/AST/ASTVisitor.h" |
| #include "swift/AST/Initializer.h" |
| #include "swift/AST/Mangle.h" |
| #include "swift/AST/Module.h" |
| #include "swift/AST/ProtocolConformance.h" |
| #include "swift/Basic/Punycode.h" |
| #include "swift/SIL/SILArgument.h" |
| #include "swift/SIL/SILType.h" |
| #include "swift/SIL/SILGlobalVariable.h" |
| #include "clang/AST/Decl.h" |
| #include "clang/AST/DeclObjC.h" |
| #include "clang/Basic/CharInfo.h" |
| #include "llvm/ADT/DenseMap.h" |
| #include "llvm/ADT/SmallString.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/ADT/StringExtras.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Support/MD5.h" |
| #include "llvm/Support/SaveAndRestore.h" |
| #include "llvm/Support/raw_ostream.h" |
| |
| using namespace swift; |
| using namespace Mangle; |
| |
| //===----------------------------------------------------------------------===// |
| // Generic Specialization |
| //===----------------------------------------------------------------------===// |
| |
| static void mangleSubstitution(Mangler &M, Substitution Sub) { |
| M.mangleType(Sub.getReplacement()->getCanonicalType(), 0); |
| for (auto C : Sub.getConformances()) { |
| if (C.isAbstract()) |
| return; |
| M.mangleProtocolConformance(C.getConcrete()); |
| } |
| } |
| |
| void GenericSpecializationMangler::mangleSpecialization() { |
| Mangler &M = getMangler(); |
| // This is a full specialization. |
| SILFunctionType *FTy = Function->getLoweredFunctionType(); |
| CanGenericSignature Sig = FTy->getGenericSignature(); |
| |
| unsigned idx = 0; |
| for (Type DepType : Sig->getAllDependentTypes()) { |
| // It is sufficient to only mangle the substitutions of the "primary" |
| // dependent types. As all other dependent types are just derived from the |
| // primary types, this will give us unique symbol names. |
| if (DepType->is<GenericTypeParamType>()) { |
| mangleSubstitution(M, Subs[idx]); |
| M.append('_'); |
| } |
| ++idx; |
| } |
| assert(idx == Subs.size() && "subs not parallel to dependent types"); |
| } |
| |
| void PartialSpecializationMangler::mangleSpecialization() { |
| Mangler &M = getMangler(); |
| // If the only change to the generic signature during specialization is |
| // addition of new same-type requirements, which happens in case of a |
| // full specialization, it would be enough to mangle only the substitutions. |
| // |
| // If the types of function arguments have not changed, but some new |
| // conformances were added to the generic parameters, e.g. in case of |
| // a pre-specialization, then it would be enough to mangle only the new |
| // generic signature. |
| // |
| // If the types of function arguments have changed as a result of a partial |
| // specialization, we need to mangle the entire new function type. |
| |
| // This is a partial specialization. |
| M.mangleType(SpecializedFnTy, 0); |
| M.append("_"); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Function Signature Optimizations |
| //===----------------------------------------------------------------------===// |
| |
| FunctionSignatureSpecializationMangler:: |
| FunctionSignatureSpecializationMangler(SpecializationPass P, Mangler &M, |
| IsFragile_t Fragile, SILFunction *F) |
| : SpecializationMangler(SpecializationKind::FunctionSignature, P, M, Fragile, F) { |
| for (unsigned i = 0, e = F->getConventions().getNumSILArguments(); i != e; |
| ++i) { |
| (void)i; |
| Args.push_back({ArgumentModifierIntBase(ArgumentModifier::Unmodified), nullptr}); |
| } |
| ReturnValue = ReturnValueModifierIntBase(ReturnValueModifier::Unmodified); |
| } |
| |
| void |
| FunctionSignatureSpecializationMangler:: |
| setArgumentDead(unsigned ArgNo) { |
| Args[ArgNo].first |= ArgumentModifierIntBase(ArgumentModifier::Dead); |
| } |
| |
| void |
| FunctionSignatureSpecializationMangler:: |
| setArgumentClosureProp(unsigned ArgNo, PartialApplyInst *PAI) { |
| auto &Info = Args[ArgNo]; |
| Info.first = ArgumentModifierIntBase(ArgumentModifier::ClosureProp); |
| Info.second = PAI; |
| } |
| |
| void |
| FunctionSignatureSpecializationMangler:: |
| setArgumentClosureProp(unsigned ArgNo, ThinToThickFunctionInst *TTTFI) { |
| auto &Info = Args[ArgNo]; |
| Info.first = ArgumentModifierIntBase(ArgumentModifier::ClosureProp); |
| Info.second = TTTFI; |
| } |
| |
| void |
| FunctionSignatureSpecializationMangler:: |
| setArgumentConstantProp(unsigned ArgNo, LiteralInst *LI) { |
| auto &Info = Args[ArgNo]; |
| Info.first = ArgumentModifierIntBase(ArgumentModifier::ConstantProp); |
| Info.second = LI; |
| } |
| |
| void |
| FunctionSignatureSpecializationMangler:: |
| setArgumentOwnedToGuaranteed(unsigned ArgNo) { |
| Args[ArgNo].first |= ArgumentModifierIntBase(ArgumentModifier::OwnedToGuaranteed); |
| } |
| |
| void |
| FunctionSignatureSpecializationMangler:: |
| setArgumentSROA(unsigned ArgNo) { |
| Args[ArgNo].first |= ArgumentModifierIntBase(ArgumentModifier::SROA); |
| } |
| |
| void |
| FunctionSignatureSpecializationMangler:: |
| setArgumentBoxToValue(unsigned ArgNo) { |
| Args[ArgNo].first = ArgumentModifierIntBase(ArgumentModifier::BoxToValue); |
| } |
| |
| void |
| FunctionSignatureSpecializationMangler:: |
| setArgumentBoxToStack(unsigned ArgNo) { |
| Args[ArgNo].first = ArgumentModifierIntBase(ArgumentModifier::BoxToStack); |
| } |
| |
| void |
| FunctionSignatureSpecializationMangler:: |
| setReturnValueOwnedToUnowned() { |
| ReturnValue |= ReturnValueModifierIntBase(ReturnValueModifier::OwnedToUnowned); |
| } |
| |
| void |
| FunctionSignatureSpecializationMangler::mangleConstantProp(LiteralInst *LI) { |
| Mangler &M = getMangler(); |
| |
| // Append the prefix for constant propagation 'cp'. |
| M.append("cp"); |
| |
| // 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(); |
| M.append("fr"); |
| M.mangleIdentifierSymbol(F->getName()); |
| break; |
| } |
| case ValueKind::GlobalAddrInst: { |
| SILGlobalVariable *G = cast<GlobalAddrInst>(LI)->getReferencedGlobal(); |
| M.append("g"); |
| M.mangleIdentifierSymbol(G->getName()); |
| break; |
| } |
| case ValueKind::IntegerLiteralInst: { |
| APInt apint = cast<IntegerLiteralInst>(LI)->getValue(); |
| M.append("i"); |
| M.mangleNatural(apint); |
| break; |
| } |
| case ValueKind::FloatLiteralInst: { |
| APInt apint = cast<FloatLiteralInst>(LI)->getBits(); |
| M.append("fl"); |
| M.mangleNatural(apint); |
| break; |
| } |
| case ValueKind::StringLiteralInst: { |
| StringLiteralInst *SLI = cast<StringLiteralInst>(LI); |
| StringRef V = SLI->getValue(); |
| |
| assert(V.size() <= 32 && "Cannot encode string of length > 32"); |
| |
| llvm::SmallString<33> Str; |
| Str += "u"; |
| Str += V; |
| M.append("se"); |
| M.mangleNatural(APInt(32, unsigned(SLI->getEncoding()))); |
| M.append("v"); |
| M.mangleIdentifier(Str); |
| break; |
| } |
| } |
| } |
| |
| void |
| FunctionSignatureSpecializationMangler:: |
| mangleClosureProp(PartialApplyInst *PAI) { |
| Mangler &M = getMangler(); |
| M.append("cl"); |
| |
| // 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. |
| auto *FRI = cast<FunctionRefInst>(PAI->getCallee()); |
| M.mangleIdentifierSymbol(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(); |
| M.mangleType(Ty.getSwiftRValueType(), 0); |
| } |
| } |
| |
| void FunctionSignatureSpecializationMangler::mangleClosureProp( |
| ThinToThickFunctionInst *TTTFI) { |
| Mangler &M = getMangler(); |
| M.append("cl"); |
| |
| // 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. |
| auto *FRI = cast<FunctionRefInst>(TTTFI->getCallee()); |
| M.mangleIdentifierSymbol(FRI->getReferencedFunction()->getName()); |
| } |
| |
| void FunctionSignatureSpecializationMangler::mangleArgument( |
| ArgumentModifierIntBase ArgMod, NullablePtr<SILInstruction> Inst) { |
| if (ArgMod == ArgumentModifierIntBase(ArgumentModifier::ConstantProp)) { |
| mangleConstantProp(cast<LiteralInst>(Inst.get())); |
| return; |
| } |
| |
| if (ArgMod == ArgumentModifierIntBase(ArgumentModifier::ClosureProp)) { |
| if (auto *PAI = dyn_cast<PartialApplyInst>(Inst.get())) { |
| mangleClosureProp(PAI); |
| return; |
| } |
| |
| auto *TTTFI = cast<ThinToThickFunctionInst>(Inst.get()); |
| mangleClosureProp(TTTFI); |
| return; |
| } |
| |
| if (ArgMod == ArgumentModifierIntBase(ArgumentModifier::Unmodified)) { |
| M.append("n"); |
| return; |
| } |
| |
| if (ArgMod == ArgumentModifierIntBase(ArgumentModifier::BoxToValue)) { |
| M.append("i"); |
| return; |
| } |
| |
| if (ArgMod == ArgumentModifierIntBase(ArgumentModifier::BoxToStack)) { |
| M.append("k"); |
| return; |
| } |
| |
| bool hasSomeMod = false; |
| if (ArgMod & ArgumentModifierIntBase(ArgumentModifier::Dead)) { |
| M.append("d"); |
| hasSomeMod = true; |
| } |
| |
| if (ArgMod & ArgumentModifierIntBase(ArgumentModifier::OwnedToGuaranteed)) { |
| M.append("g"); |
| hasSomeMod = true; |
| } |
| if (ArgMod & ArgumentModifierIntBase(ArgumentModifier::SROA)) { |
| M.append("s"); |
| hasSomeMod = true; |
| } |
| |
| assert(hasSomeMod && "Unknown modifier"); |
| } |
| |
| void FunctionSignatureSpecializationMangler:: |
| mangleReturnValue(ReturnValueModifierIntBase RetMod) { |
| if (RetMod == ReturnValueModifierIntBase(ReturnValueModifier::Unmodified)) { |
| return; |
| } |
| |
| if (RetMod & ReturnValueModifierIntBase(ReturnValueModifier::Dead)) { |
| M.append("d"); |
| } |
| |
| if (RetMod & ReturnValueModifierIntBase(ReturnValueModifier::OwnedToUnowned)) { |
| M.append("g"); |
| } |
| } |
| |
| void FunctionSignatureSpecializationMangler::mangleSpecialization() { |
| |
| for (unsigned i : indices(Args)) { |
| ArgumentModifierIntBase ArgMod; |
| NullablePtr<SILInstruction> Inst; |
| std::tie(ArgMod, Inst) = Args[i]; |
| mangleArgument(ArgMod, Inst); |
| M.append("_"); |
| } |
| |
| mangleReturnValue(ReturnValue); |
| } |