<commit_before>//===--- Mangle.cpp - Swift Name Mangling --------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements declaration name mangling in Swift.
//
//===----------------------------------------------------------------------===//

#include "swift/AST/Attr.h"
#include "swift/AST/Types.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Module.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ErrorHandling.h"

#include "IRGenModule.h"
#include "Linking.h"
#include "IRGen.h"

using namespace swift;
using namespace irgen;

/// Translate the given operator character into its mangled form.
///
/// Current operator characters:    /=-+*%<>!&|^~ and the special operator '..'
static char mangleOperatorChar(char op) {
  switch (op) {
  case '&': return 'a'; // 'and'
  case '/': return 'd'; // 'divide'
  case '=': return 'e'; // 'equal'
  case '>': return 'g'; // 'greater'
  case '<': return 'l'; // 'less'
  case '*': return 'm'; // 'multiply'
  case '!': return 'n'; // 'negate'
  case '|': return 'o'; // 'or'
  case '+': return 'p'; // 'plus'
  case '%': return 'r'; // 'remainder'
  case '-': return 's'; // 'subtract'
  case '^': return 'x'; // 'xor'
  case '~': return 't'; // 'tilde'
  case '.': return 'z'; // 'period'
  default: llvm_unreachable("bad identifier character");
  }
}

namespace {
  /// A class for mangling declarations.
  class Mangler {
    raw_ostream &Buffer;
    llvm::DenseMap<void*, unsigned> Substitutions;

  public:
    Mangler(raw_ostream &buffer) : Buffer(buffer) {}
    void mangleDeclName(ValueDecl *decl);
    void mangleType(Type type, ExplosionKind kind, unsigned uncurryingLevel);

  private:
    void mangleDeclContext(DeclContext *ctx);
    void mangleIdentifier(Identifier ident);
    bool tryMangleSubstitution(void *ptr);
    void addSubstitution(void *ptr);
  };
}

/// Mangle an identifier into the buffer.
void Mangler::mangleIdentifier(Identifier ident) {
  StringRef str = ident.str();
  assert(!str.empty() && "mangling an empty identifier!");

  // Mangle normal identifiers as
  //   count identifier-char+
  // where the count is the number of characters in the identifier,
  // and where individual identifier characters represent themselves.
  if (!ident.isOperator()) {
    Buffer << str.size() << str;
    return;
  }

  // Mangle operator identifiers as
  //   'op' count operator-char+
  // where the count is the number of characters in the operator,
  // and where the individual operator characters are translated.
  Buffer << "op";

  Buffer << str.size();
  for (unsigned i = 0, e = str.size(); i != e; ++i) {
    Buffer << mangleOperatorChar(str[i]);
  }
}

bool Mangler::tryMangleSubstitution(void *ptr) {
  auto ir = Substitutions.find(ptr);
  if (ir == Substitutions.end()) return false;

  // substitution ::= 'S' integer? '_'

  unsigned index = ir->second;
  Buffer << 'S';
  if (index) Buffer << (index - 1);
  Buffer << '_';
  return true;
}

void Mangler::addSubstitution(void *ptr) {
  Substitutions.insert(std::make_pair(ptr, Substitutions.size()));
}

void Mangler::mangleDeclContext(DeclContext *ctx) {
  switch (ctx->getContextKind()) {
  case DeclContextKind::BuiltinModule:
    llvm_unreachable("mangling member of builtin module!");

  case DeclContextKind::TranslationUnit: {
    Module *module = cast<Module>(ctx);

    // Try the special 'swift' substitution.
    // context ::= Ss
    if (!module->getParent() && module->Name.str() == "swift") {
      Buffer << "Ss";
      return;
    }

    // context ::= substitution identifier*
    // context ::= identifier+

    if (tryMangleSubstitution(module)) return;

    if (DeclContext *parent = module->getParent())
      mangleDeclContext(parent);

    // This should work, because the language should be restricting
    // the name of a module to be a valid language identifier.
    mangleIdentifier(module->Name);
    addSubstitution(module);
    return;
  }

  case DeclContextKind::DistinctTypeDecl: {
    if (isa<OneOfDecl>(ctx) || isa<StructDecl>(ctx) || isa<ClassDecl>(ctx)) {
      // FIXME: The mangling rule here is kind of weird.
      mangleType(cast<DistinctTypeDecl>(ctx)->getDeclaredType(),
                 ExplosionKind::Minimal, 0);
      return;
    }
    // It's not clear what would be mangled for protocols.
    llvm_unreachable("Unexpected context");
  }

  case DeclContextKind::ExtensionDecl:
    // Mandle the extension as the original type.
    mangleType(cast<ExtensionDecl>(ctx)->getExtendedType(),
               ExplosionKind::Minimal, 0);
    return;

  case DeclContextKind::CapturingExpr:
  case DeclContextKind::TopLevelCodeDecl:
    // FIXME: we don't need to agree about these across components, but
    // that's no excuse for not mangling *something* in here.
    break;<commit_msg>Minor fix for mangling; I wasn't trying to change the mangling of oneofs with my last commit.<commit_after>//===--- Mangle.cpp - Swift Name Mangling --------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements declaration name mangling in Swift.
//
//===----------------------------------------------------------------------===//

#include "swift/AST/Attr.h"
#include "swift/AST/Types.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Module.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ErrorHandling.h"

#include "IRGenModule.h"
#include "Linking.h"
#include "IRGen.h"

using namespace swift;
using namespace irgen;

/// Translate the given operator character into its mangled form.
///
/// Current operator characters:    /=-+*%<>!&|^~ and the special operator '..'
static char mangleOperatorChar(char op) {
  switch (op) {
  case '&': return 'a'; // 'and'
  case '/': return 'd'; // 'divide'
  case '=': return 'e'; // 'equal'
  case '>': return 'g'; // 'greater'
  case '<': return 'l'; // 'less'
  case '*': return 'm'; // 'multiply'
  case '!': return 'n'; // 'negate'
  case '|': return 'o'; // 'or'
  case '+': return 'p'; // 'plus'
  case '%': return 'r'; // 'remainder'
  case '-': return 's'; // 'subtract'
  case '^': return 'x'; // 'xor'
  case '~': return 't'; // 'tilde'
  case '.': return 'z'; // 'period'
  default: llvm_unreachable("bad identifier character");
  }
}

namespace {
  /// A class for mangling declarations.
  class Mangler {
    raw_ostream &Buffer;
    llvm::DenseMap<void*, unsigned> Substitutions;

  public:
    Mangler(raw_ostream &buffer) : Buffer(buffer) {}
    void mangleDeclName(ValueDecl *decl);
    void mangleType(Type type, ExplosionKind kind, unsigned uncurryingLevel);

  private:
    void mangleDeclContext(DeclContext *ctx);
    void mangleIdentifier(Identifier ident);
    bool tryMangleSubstitution(void *ptr);
    void addSubstitution(void *ptr);
  };
}

/// Mangle an identifier into the buffer.
void Mangler::mangleIdentifier(Identifier ident) {
  StringRef str = ident.str();
  assert(!str.empty() && "mangling an empty identifier!");

  // Mangle normal identifiers as
  //   count identifier-char+
  // where the count is the number of characters in the identifier,
  // and where individual identifier characters represent themselves.
  if (!ident.isOperator()) {
    Buffer << str.size() << str;
    return;
  }

  // Mangle operator identifiers as
  //   'op' count operator-char+
  // where the count is the number of characters in the operator,
  // and where the individual operator characters are translated.
  Buffer << "op";

  Buffer << str.size();
  for (unsigned i = 0, e = str.size(); i != e; ++i) {
    Buffer << mangleOperatorChar(str[i]);
  }
}

bool Mangler::tryMangleSubstitution(void *ptr) {
  auto ir = Substitutions.find(ptr);
  if (ir == Substitutions.end()) return false;

  // substitution ::= 'S' integer? '_'

  unsigned index = ir->second;
  Buffer << 'S';
  if (index) Buffer << (index - 1);
  Buffer << '_';
  return true;
}

void Mangler::addSubstitution(void *ptr) {
  Substitutions.insert(std::make_pair(ptr, Substitutions.size()));
}

void Mangler::mangleDeclContext(DeclContext *ctx) {
  switch (ctx->getContextKind()) {
  case DeclContextKind::BuiltinModule:
    llvm_unreachable("mangling member of builtin module!");

  case DeclContextKind::TranslationUnit: {
    Module *module = cast<Module>(ctx);

    // Try the special 'swift' substitution.
    // context ::= Ss
    if (!module->getParent() && module->Name.str() == "swift") {
      Buffer << "Ss";
      return;
    }

    // context ::= substitution identifier*
    // context ::= identifier+

    if (tryMangleSubstitution(module)) return;

    if (DeclContext *parent = module->getParent())
      mangleDeclContext(parent);

    // This should work, because the language should be restricting
    // the name of a module to be a valid language identifier.
    mangleIdentifier(module->Name);
    addSubstitution(module);
    return;
  }

  case DeclContextKind::DistinctTypeDecl: {
    if (isa<OneOfDecl>(ctx)) {
      OneOfDecl *oneof = cast<OneOfDecl>(ctx);

      // FIXME: The mangling rule here is kind of weird.
      if (tryMangleSubstitution(oneof->getDeclaredType())) return;
      mangleDeclContext(ctx->getParent());
      mangleIdentifier(oneof->getName());
      addSubstitution(oneof->getDeclaredType());
      return;
    }
    if (isa<StructDecl>(ctx) || isa<ClassDecl>(ctx)) {
      // FIXME: The mangling rule here is kind of weird.
      mangleType(cast<DistinctTypeDecl>(ctx)->getDeclaredType(),
                 ExplosionKind::Minimal, 0);
      return;
    }
    // It's not clear what would be mangled for protocols.
    llvm_unreachable("Unexpected context");
  }

  case DeclContextKind::ExtensionDecl:
    // Mandle the extension as the original type.
    mangleType(cast<ExtensionDecl>(ctx)->getExtendedType(),
               ExplosionKind::Minimal, 0);
    return;

  case DeclContextKind::CapturingExpr:
  case DeclContextKind::TopLevelCodeDecl:
    // FIXME: we don't need to agree about these across components, but
    // that's no excuse for not mangling *something* in here.
    break;
{'fraction_non_alphanumeric': 0.17652949745083757, 'fraction_numerical': 0.0025491624180626364, 'mean_word_length': 2.972875226039783, 'pattern_counts': {'":': 0, '<': 58, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7420355', 'n_tokens_mistral': 3423, 'n_tokens_neox': 3255, 'n_words': 961}