//===--- Linking.cpp - Name mangling for IRGen entities -------------------===//
//
// 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 name mangling for IRGen entities with linkage.
//
//===----------------------------------------------------------------------===//

#include "Linking.h"
#include "IRGenMangler.h"
#include "llvm/Support/raw_ostream.h"
#include "swift/Basic/Fallthrough.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "swift/SIL/SILGlobalVariable.h"
#include "swift/AST/Mangle.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"

using namespace swift;
using namespace irgen;
using namespace Mangle;

static StringRef mangleValueWitness(ValueWitness witness) {
  // The ones with at least one capital are the composite ops, and the
  // capitals correspond roughly to the positions of buffers (as
  // opposed to objects) in the arguments.  That doesn't serve any
  // direct purpose, but it's neat.
  switch (witness) {
#define VALUE_WITNESS(MANGLING, NAME) \
    case ValueWitness::NAME: return #MANGLING;
#include "swift/Basic/ValueWitnessMangling.def"

  case ValueWitness::Size:
  case ValueWitness::Flags:
  case ValueWitness::Stride:
  case ValueWitness::ExtraInhabitantFlags:
    llvm_unreachable("not a function witness");
  }
  llvm_unreachable("bad witness kind");
}

/// Mangle this entity as a std::string.
std::string LinkEntity::mangleAsString() const {
  std::string result; {
    llvm::raw_string_ostream stream(result);
    mangle(stream);
  }
  return result;
}

/// Mangle this entity into the given buffer.
void LinkEntity::mangle(SmallVectorImpl<char> &buffer) const {
  llvm::raw_svector_ostream stream(buffer);
  mangle(stream);
}

/// Use the Clang importer to mangle a Clang declaration.
static void mangleClangDecl(raw_ostream &buffer,
                            const clang::NamedDecl *clangDecl,
                            ASTContext &ctx) {
  auto *importer = static_cast<ClangImporter *>(ctx.getClangModuleLoader());
  importer->getMangledName(buffer, clangDecl);
}

/// Mangle this entity into the given stream.
void LinkEntity::mangle(raw_ostream &buffer) const {
  std::string Old = mangleOld();
  std::string New = mangleNew();

  std::string Result = NewMangling::selectMangling(Old, New);
  buffer.write(Result.data(), Result.size());
}

/// Mangle this entity into the given stream.
std::string LinkEntity::mangleOld() const {
  // Almost everything below gets the common prefix:
  //   mangled-name ::= '_T' global
  Mangler mangler;
  switch (getKind()) {
  //   global ::= 'w' value-witness-kind type     // value witness
  case Kind::ValueWitness:
    mangler.append("_Tw");
    mangler.append(mangleValueWitness(getValueWitness()));
    mangler.mangleType(getType(), 0);
    return mangler.finalize();

  //   global ::= 'WV' type                       // value witness
  case Kind::ValueWitnessTable:
    mangler.append("_TWV");
    mangler.mangleType(getType(), 0);
    return mangler.finalize();

  //   global ::= 't' type
  // Abstract type manglings just follow <type>.
  case Kind::TypeMangling:
    mangler.mangleType(getType(), 0);
    return mangler.finalize();

  //   global ::= 'Ma' type               // type metadata access function
  case Kind::TypeMetadataAccessFunction:
    mangler.append("_TMa");
    mangler.mangleType(getType(), 0);
    return mangler.finalize();

  //   global ::= 'ML' type               // type metadata lazy cache variable
  case Kind::TypeMetadataLazyCacheVariable:
    mangler.append("_TML");
    mangler.mangleType(getType(), 0);
    return mangler.finalize();

  //   global ::= 'Mf' type                       // 'full' type metadata
  //   global ::= 'M' directness type             // type metadata
  //   global ::= 'MP' directness type            // type metadata pattern
  case Kind::TypeMetadata:
    switch (getMetadataAddress()) {
    case TypeMetadataAddress::FullMetadata:
      mangler.mangleTypeFullMetadataFull(getType());
      break;
    case TypeMetadataAddress::AddressPoint:
      mangler.mangleTypeMetadataFull(getType(), isMetadataPattern());
      break;
    }
    return mangler.finalize();

  //   global ::= 'M' directness type             // type metadata
  case Kind::ForeignTypeMetadataCandidate:
    mangler.mangleTypeMetadataFull(getType(), /*isPattern=*/false);
    return mangler.finalize();

  //   global ::= 'Mm' type                       // class metaclass
  case Kind::SwiftMetaclassStub:
    mangler.append("_TMm");
    mangler.mangleNominalType(cast<ClassDecl>(getDecl()));
    return mangler.finalize();

  //   global ::= 'Mn' type                       // nominal type descriptor
  case Kind::NominalTypeDescriptor:
    mangler.append("_TMn");
    mangler.mangleNominalType(cast<NominalTypeDecl>(getDecl()));
    return mangler.finalize();

  //   global ::= 'Mp' type                       // protocol descriptor
  case Kind::ProtocolDescriptor:
    mangler.append("_TMp");
    mangler.mangleProtocolName(cast<ProtocolDecl>(getDecl()));
    return mangler.finalize();

  //   global ::= 'Wo' entity
  case Kind::WitnessTableOffset:
     mangler.append("_TWo");

    // Witness table entries for constructors always refer to the allocating
    // constructor.
    if (auto ctor = dyn_cast<ConstructorDecl>(getDecl()))
      mangler.mangleConstructorEntity(ctor, /*isAllocating=*/true,
                                      getUncurryLevel());
    else
      mangler.mangleEntity(getDecl(), getUncurryLevel());
    return mangler.finalize();

  //   global ::= 'Wv' directness entity
  case Kind::FieldOffset:
    mangler.mangleFieldOffsetFull(getDecl(), isOffsetIndirect());
    return mangler.finalize();

  //   global ::= 'WP' protocol-conformance
  case Kind::DirectProtocolWitnessTable:
    mangler.append("_TWP");
    mangler.mangleProtocolConformance(getProtocolConformance());
    return mangler.finalize();

  //   global ::= 'WG' protocol-conformance
  case Kind::GenericProtocolWitnessTableCache:
    mangler.mangleProtocolConformance(getProtocolConformance());
    return std::string("_TWG") + mangler.finalize();

  //   global ::= 'WI' protocol-conformance
  case Kind::GenericProtocolWitnessTableInstantiationFunction:
    mangler.mangleProtocolConformance(getProtocolConformance());
    return std::string("_TWI") + mangler.finalize();

  //   global ::= 'Wa' protocol-conformance
  case Kind::ProtocolWitnessTableAccessFunction:
    mangler.append("_TWa");
    mangler.mangleProtocolConformance(getProtocolConformance());
    return mangler.finalize();

  //   global ::= 'Wl' type protocol-conformance
  case Kind::ProtocolWitnessTableLazyAccessFunction:
    mangler.append("_TWl");
    mangler.mangleType(getType(), 0);
    mangler.mangleProtocolConformance(getProtocolConformance());
    return mangler.finalize();

  //   global ::= 'WL' type protocol-conformance
  case Kind::ProtocolWitnessTableLazyCacheVariable:
    mangler.append("_TWL");
    mangler.mangleType(getType(), 0);
    mangler.mangleProtocolConformance(getProtocolConformance());
    return mangler.finalize();
      
  //   global ::= 'Wt' protocol-conformance identifier
  case Kind::AssociatedTypeMetadataAccessFunction:
    mangler.append("_TWt");
    mangler.mangleProtocolConformance(getProtocolConformance());
    mangler.mangleIdentifier(getAssociatedType()->getNameStr());
    return mangler.finalize();

  //   global ::= 'WT' protocol-conformance identifier nominal-type
  case Kind::AssociatedTypeWitnessTableAccessFunction:
    mangler.append("_TWT");
    mangler.mangleProtocolConformance(getProtocolConformance());
    mangler.mangleIdentifier(getAssociatedType()->getNameStr());
    mangler.mangleProtocolDecl(getAssociatedProtocol());
    return mangler.finalize();

  // For all the following, this rule was imposed above:
  //   global ::= local-marker? entity            // some identifiable thing

  //   entity ::= declaration                     // other declaration
  case Kind::Function:
    // As a special case, functions can have manually mangled names.
    if (auto AsmA = getDecl()->getAttrs().getAttribute<SILGenNameAttr>()) {
      mangler.append(AsmA->Name);
      return mangler.finalize();
    }

    // Otherwise, fall through into the 'other decl' case.
    SWIFT_FALLTHROUGH;

  case Kind::Other:
    // As a special case, Clang functions and globals don't get mangled at all.
    if (auto clangDecl = getDecl()->getClangDecl()) {
      if (auto namedClangDecl = dyn_cast<clang::DeclaratorDecl>(clangDecl)) {
        if (auto asmLabel = namedClangDecl->getAttr<clang::AsmLabelAttr>()) {
          mangler.append('\01');
          mangler.append(asmLabel->getLabel());
        } else if (namedClangDecl->hasAttr<clang::OverloadableAttr>()) {
          // FIXME: When we can import C++, use Clang's mangler all the time.
          std::string storage;
          llvm::raw_string_ostream SS(storage);
          mangleClangDecl(SS, namedClangDecl, getDecl()->getASTContext());
          mangler.append(SS.str());
        } else {
          mangler.append(namedClangDecl->getName());
        }
        return mangler.finalize();
      }
    }

    mangler.append("_T");
    if (auto type = dyn_cast<NominalTypeDecl>(getDecl())) {
      mangler.mangleNominalType(type);
    } else if (auto ctor = dyn_cast<ConstructorDecl>(getDecl())) {
      // FIXME: Hack. LinkInfo should be able to refer to the allocating
      // constructor rather than inferring it here.
      mangler.mangleConstructorEntity(ctor, /*isAllocating=*/true,
                                      getUncurryLevel());
    } else {
      mangler.mangleEntity(getDecl(), getUncurryLevel());
    }
      return mangler.finalize();

  // An Objective-C class reference reference. The symbol is private, so
  // the mangling is unimportant; it should just be readable in LLVM IR.
  case Kind::ObjCClassRef: {
    mangler.append("OBJC_CLASS_REF_$_");
    llvm::SmallString<64> tempBuffer;
    StringRef name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(tempBuffer);
    mangler.append(name);
    return mangler.finalize();
  }

  // An Objective-C class reference;  not a swift mangling.
  case Kind::ObjCClass: {
    llvm::SmallString<64> TempBuffer;
    mangler.append("OBJC_CLASS_$_");
    StringRef Name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(TempBuffer);
    mangler.append(Name);
    return mangler.finalize();
  }

  // An Objective-C metaclass reference;  not a swift mangling.
  case Kind::ObjCMetaclass: {
    llvm::SmallString<64> TempBuffer;
    mangler.append("OBJC_METACLASS_$_");
    StringRef Name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(TempBuffer);
    mangler.append(Name);
    return mangler.finalize();
  }

  case Kind::SILFunction:
    mangler.appendSymbol(getSILFunction()->getName());
    return mangler.finalize();
  case Kind::SILGlobalVariable:
    mangler.appendSymbol(getSILGlobalVariable()->getName());
    return mangler.finalize();

  case Kind::ReflectionBuiltinDescriptor:
    mangler.append("_TMRb");
    mangler.mangleType(getType(), getUncurryLevel());
    return mangler.finalize();
  case Kind::ReflectionFieldDescriptor:
    mangler.append("_TMRf");
    mangler.mangleType(getType(), getUncurryLevel());
    return mangler.finalize();
  case Kind::ReflectionAssociatedTypeDescriptor:
    mangler.append("_TMRa");
    mangler.mangleProtocolConformance(getProtocolConformance());
    return mangler.finalize();
  case Kind::ReflectionSuperclassDescriptor:
    mangler.append("_TMRs");
    mangler.mangleNominalType(cast<ClassDecl>(getDecl()));
    return mangler.finalize();
  }
  llvm_unreachable("bad entity kind!");
}

/// Mangle this entity into the given stream.
std::string LinkEntity::mangleNew() const {
  // Almost everything below gets the common prefix:
  //   mangled-name ::= '_T' global
  IRGenMangler mangler;
  switch (getKind()) {
      //   global ::= 'w' value-witness-kind          // value witness
    case Kind::ValueWitness:
      return mangler.mangleValueWitness(getType(), getValueWitness());

      //   global ::= 'WV' type                       // value witness
    case Kind::ValueWitnessTable:
      return mangler.mangleValueWitnessTable(getType());

      //   global ::= 't' type
      // Abstract type manglings just follow <type>.
    case Kind::TypeMangling:
      return mangleOld();

      //   global ::= 'Ma' type               // type metadata access function
    case Kind::TypeMetadataAccessFunction:
      return mangler.mangleTypeMetadataAccessFunction(getType());

      //   global ::= 'ML' type               // type metadata lazy cache variable
    case Kind::TypeMetadataLazyCacheVariable:
      return mangler.mangleTypeMetadataLazyCacheVariable(getType());

      //   global ::= 'Mf' type                       // 'full' type metadata
      //   global ::= 'M' directness type             // type metadata
      //   global ::= 'MP' directness type            // type metadata pattern
    case Kind::TypeMetadata:
      switch (getMetadataAddress()) {
        case TypeMetadataAddress::FullMetadata:
          return mangler.mangleTypeFullMetadataFull(getType());
        case TypeMetadataAddress::AddressPoint:
          return mangler.mangleTypeMetadataFull(getType(), isMetadataPattern());
      }
      llvm_unreachable("invalid metadata address");

      //   global ::= 'M' directness type             // type metadata
    case Kind::ForeignTypeMetadataCandidate:
      return mangler.mangleTypeMetadataFull(getType(), /*isPattern=*/false);

      //   global ::= 'Mm' type                       // class metaclass
    case Kind::SwiftMetaclassStub:
      return mangler.mangleClassMetaClass(cast<ClassDecl>(getDecl()));

      //   global ::= 'Mn' type                       // nominal type descriptor
    case Kind::NominalTypeDescriptor:
      return mangler.mangleNominalTypeDescriptor(
                                          cast<NominalTypeDecl>(getDecl()));

      //   global ::= 'Mp' type                       // protocol descriptor
    case Kind::ProtocolDescriptor:
      return mangler.mangleProtocolDescriptor(cast<ProtocolDecl>(getDecl()));

      //   global ::= 'Wo' entity
    case Kind::WitnessTableOffset:
      return mangler.mangleWitnessTableOffset(getDecl());

      //   global ::= 'Wv' directness entity
    case Kind::FieldOffset:
      return mangler.mangleFieldOffsetFull(getDecl(), isOffsetIndirect());

      //   global ::= 'WP' protocol-conformance
    case Kind::DirectProtocolWitnessTable:
      return mangler.mangleDirectProtocolWitnessTable(getProtocolConformance());

      //   global ::= 'WG' protocol-conformance
    case Kind::GenericProtocolWitnessTableCache:
      return mangler.mangleGenericProtocolWitnessTableCache(
                                                      getProtocolConformance());

      //   global ::= 'WI' protocol-conformance
    case Kind::GenericProtocolWitnessTableInstantiationFunction:
      return mangler.mangleGenericProtocolWitnessTableInstantiationFunction(
                                                      getProtocolConformance());

      //   global ::= 'Wa' protocol-conformance
    case Kind::ProtocolWitnessTableAccessFunction:
      return mangler.mangleProtocolWitnessTableAccessFunction(
                                                      getProtocolConformance());

      //   global ::= 'Wl' type protocol-conformance
    case Kind::ProtocolWitnessTableLazyAccessFunction:
      return mangler.mangleProtocolWitnessTableLazyAccessFunction(getType(),
                                                      getProtocolConformance());

      //   global ::= 'WL' type protocol-conformance
    case Kind::ProtocolWitnessTableLazyCacheVariable:
      return mangler.mangleProtocolWitnessTableLazyCacheVariable(getType(),
                                                      getProtocolConformance());

      //   global ::= 'Wt' protocol-conformance identifier
    case Kind::AssociatedTypeMetadataAccessFunction:
      return mangler.mangleAssociatedTypeMetadataAccessFunction(
                  getProtocolConformance(), getAssociatedType()->getNameStr());

      //   global ::= 'WT' protocol-conformance identifier nominal-type
    case Kind::AssociatedTypeWitnessTableAccessFunction:
      return mangler.mangleAssociatedTypeWitnessTableAccessFunction(
                  getProtocolConformance(), getAssociatedType()->getNameStr(),
                  getAssociatedProtocol());

      // For all the following, this rule was imposed above:
      //   global ::= local-marker? entity            // some identifiable thing

      //   entity ::= declaration                     // other declaration
    case Kind::Function:
      // As a special case, functions can have manually mangled names.
      if (auto AsmA = getDecl()->getAttrs().getAttribute<SILGenNameAttr>()) {
        return AsmA->Name;
      }

      // Otherwise, fall through into the 'other decl' case.
      SWIFT_FALLTHROUGH;

    case Kind::Other:
      // As a special case, Clang functions and globals don't get mangled at all.
      if (auto clangDecl = getDecl()->getClangDecl()) {
        if (auto namedClangDecl = dyn_cast<clang::DeclaratorDecl>(clangDecl)) {
          if (auto asmLabel = namedClangDecl->getAttr<clang::AsmLabelAttr>()) {
            std::string Name(1, '\01');
            Name.append(asmLabel->getLabel());
            return Name;
          }
          if (namedClangDecl->hasAttr<clang::OverloadableAttr>()) {
            // FIXME: When we can import C++, use Clang's mangler all the time.
            std::string storage;
            llvm::raw_string_ostream SS(storage);
            mangleClangDecl(SS, namedClangDecl, getDecl()->getASTContext());
            return SS.str();
          }
          return namedClangDecl->getName();
        }
      }

      if (auto type = dyn_cast<NominalTypeDecl>(getDecl())) {
        return mangler.mangleNominalType(type);
      }
      if (auto ctor = dyn_cast<ConstructorDecl>(getDecl())) {
        // FIXME: Hack. LinkInfo should be able to refer to the allocating
        // constructor rather than inferring it here.
        return mangler.mangleConstructorEntity(ctor, /*isAllocating=*/true,
                                               /*isCurried=*/false);
      }
      return mangler.mangleEntity(getDecl(), /*isCurried=*/false);

      // An Objective-C class reference reference. The symbol is private, so
      // the mangling is unimportant; it should just be readable in LLVM IR.
    case Kind::ObjCClassRef: {
      llvm::SmallString<64> tempBuffer;
      StringRef name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(tempBuffer);
      std::string Result("OBJC_CLASS_REF_$_");
      Result.append(name.data(), name.size());
      return Result;
    }

      // An Objective-C class reference;  not a swift mangling.
    case Kind::ObjCClass: {
      llvm::SmallString<64> TempBuffer;
      StringRef Name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(TempBuffer);
      std::string Result("OBJC_CLASS_$_");
      Result.append(Name.data(), Name.size());
      return Result;
    }

      // An Objective-C metaclass reference;  not a swift mangling.
    case Kind::ObjCMetaclass: {
      llvm::SmallString<64> TempBuffer;
      StringRef Name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(TempBuffer);
      std::string Result("OBJC_METACLASS_$_");
      Result.append(Name.data(), Name.size());
      return Result;
    }

    case Kind::SILFunction:
      return getSILFunction()->getName();
    case Kind::SILGlobalVariable:
      return getSILGlobalVariable()->getName();

    case Kind::ReflectionBuiltinDescriptor:
      return mangler.mangleReflectionBuiltinDescriptor(getType());
    case Kind::ReflectionFieldDescriptor:
      return mangler.mangleReflectionFieldDescriptor(getType());
    case Kind::ReflectionAssociatedTypeDescriptor:
      return mangler.mangleReflectionAssociatedTypeDescriptor(
                                                      getProtocolConformance());
    case Kind::ReflectionSuperclassDescriptor:
      return mangler.mangleReflectionSuperclassDescriptor(
                                                    cast<ClassDecl>(getDecl()));
  }
  llvm_unreachable("bad entity kind!");
}
