//===--- TBDGen.cpp - Swift TBD Generation --------------------------------===//
//
// 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 the entrypoints into TBD file generation.
//
//===----------------------------------------------------------------------===//

#include "swift/TBDGen/TBDGen.h"

#include "swift/AST/ASTMangler.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/Module.h"
#include "swift/Basic/LLVM.h"
#include "swift/IRGen/LinkEntity.h"
#include "swift/SIL/FormalLinkage.h"
#include "swift/SIL/SILDeclRef.h"
#include "llvm/ADT/StringSet.h"

using namespace swift;
using StringSet = llvm::StringSet<>;

static bool isPrivateDecl(ValueDecl *VD) {
  return getDeclLinkage(VD) != FormalLinkage::PublicUnique;
}

namespace {
class TBDGenVisitor : public ASTVisitor<TBDGenVisitor> {
  StringSet &Symbols;

  void addSymbol(StringRef name) {
    assert(Symbols.insert(name).second && "already inserted");
  }

  void visitValueTypeDecl(NominalTypeDecl *NTD) {
    assert(isa<StructDecl>(NTD) || isa<EnumDecl>(NTD));
    if (isPrivateDecl(NTD))
      return;

    auto declaredType = NTD->getDeclaredType()->getCanonicalType();

    auto vwt = irgen::LinkEntity::forValueWitnessTable(declaredType);
    addSymbol(vwt.mangleAsString());

    visitNominalTypeDecl(NTD);
  }

public:
  TBDGenVisitor(StringSet &symbols) : Symbols(symbols) {}

  void visitMembers(Decl *D) {
    SmallVector<Decl *, 4> members;
    auto addMembers = [&](DeclRange range) {
      for (auto member : range)
        members.push_back(member);
    };
    if (auto ED = dyn_cast<ExtensionDecl>(D))
      addMembers(ED->getMembers());
    else if (auto NTD = dyn_cast<NominalTypeDecl>(D))
      addMembers(NTD->getMembers());

    for (auto member : members) {
      ASTVisitor::visit(member);
    }
  }
  void visitValueDecl(ValueDecl *VD) {
    if (isPrivateDecl(VD))
      return;

    auto declRef = SILDeclRef(VD);
    addSymbol(declRef.mangle());

    visitMembers(VD);
  }
  void visitTypeAliasDecl(TypeAliasDecl *TAD) {
    // any information here is encoded elsewhere
  }
  void visitNominalTypeDecl(NominalTypeDecl *NTD) {
    auto declaredType = NTD->getDeclaredType()->getCanonicalType();

    auto ntDescriptor = irgen::LinkEntity::forNominalTypeDescriptor(NTD);
    addSymbol(ntDescriptor.mangleAsString());

    auto tmd = irgen::LinkEntity::forTypeMetadata(
        declaredType, irgen::TypeMetadataAddress::AddressPoint,
        /*isPattern=*/false);
    addSymbol(tmd.mangleAsString());
    auto tmda = irgen::LinkEntity::forTypeMetadataAccessFunction(declaredType);
    addSymbol(tmda.mangleAsString());

    if (isPrivateDecl(NTD))
      return;

    visitMembers(NTD);
  }
  void visitClassDecl(ClassDecl *CD) {
    if (isPrivateDecl(CD))
      return;

    auto declaredType = CD->getDeclaredType()->getCanonicalType();

    auto tmlcv =
        irgen::LinkEntity::forTypeMetadataLazyCacheVariable(declaredType);
    addSymbol(tmlcv.mangleAsString());

    visitNominalTypeDecl(CD);
  }

  void visitStructDecl(StructDecl *SD) { visitValueTypeDecl(SD); }
  void visitEnumDecl(EnumDecl *ED) { visitValueTypeDecl(ED); }
  void visitProtocolDecl(ProtocolDecl *PD) {
    if (isPrivateDecl(PD))
      return;

    auto pDescriptor = irgen::LinkEntity::forProtocolDescriptor(PD);
    addSymbol(pDescriptor.mangleAsString());

    // There's no relevant information about members of a protocol at individual
    // protocols, each conforming type has to handle them individually.
  }

  void visitVarDecl(VarDecl *VD);

  void visitDecl(Decl *D) { visitMembers(D); }
};
}

void TBDGenVisitor::visitVarDecl(VarDecl *VD) {
  if (isPrivateDecl(VD))
    return;

  // statically/globally stored variables have some special handling.
  if (VD->hasStorage() &&
      (VD->isStatic() || VD->getDeclContext()->isModuleScopeContext())) {
    // The actual variable has a symbol, even when private.
    Mangle::ASTMangler mangler;
    addSymbol(mangler.mangleEntity(VD, false));

    auto accessor = SILDeclRef(VD, SILDeclRef::Kind::GlobalAccessor);
    addSymbol(accessor.mangle());
  }

  visitMembers(VD);
}

void swift::enumeratePublicSymbols(FileUnit *file, StringSet &symbols) {
  SmallVector<Decl *, 16> decls;
  file->getTopLevelDecls(decls);

  TBDGenVisitor visitor(symbols);
  for (auto d : decls)
    visitor.visit(d);
}
