Files
codeql/swift/extractor/mangler/SwiftMangler.cpp
Alex Denisov 125aab8107 Swift: rework fetching and dispatching
* visiting now happens in a later stage than fetching labels. While
  fetching a list of entities to be visited is created, and then acted
  upon in actual extraction. This partially flattens the recursive
  nature of `fetchLabel` into a loop inside `SwiftVisitor::extract`.
  Recursion in `fetchLabel` will only happen on labels fetched while
  naming an entity (calling into `SwiftMangler`).
* The choice whether to name a declaration or type has been moved from
  the translators to `SwiftMangler`. Acting on this choice is contained
  in `SwiftDispatcher::createLabel`.
* The choice whether to emit a body of a declaration has been moved from
  `DeclTranslator` to the dispatcher. This choice is also contained in
  `SwiftDispatcher::createLabel`.
* The simple functionality of the `LabelStore` has been moved to the
  `SwiftDispatcher` as well.
2023-04-25 11:15:27 +02:00

90 lines
3.0 KiB
C++

#include "swift/extractor/mangler/SwiftMangler.h"
#include "swift/extractor/infra/SwiftDispatcher.h"
#include "swift/extractor/trap/generated/decl/TrapClasses.h"
#include <swift/AST/Module.h>
#include <sstream>
using namespace codeql;
namespace {
SwiftMangledName initMangled(const swift::TypeBase* type) {
switch (type->getKind()) {
#define TYPE(ID, PARENT) \
case swift::TypeKind::ID: \
return {{#ID "Type_"}};
#include <swift/AST/TypeNodes.def>
default:
return {};
}
}
SwiftMangledName initMangled(const swift::Decl* decl) {
SwiftMangledName ret;
ret << swift::Decl::getKindName(decl->getKind()) << "Decl_";
return ret;
}
} // namespace
SwiftMangledName SwiftMangler::mangleModuleName(std::string_view name) {
SwiftMangledName ret = {{"ModuleDecl_"}};
ret << name;
return ret;
}
SwiftMangledName SwiftMangler::mangleDecl(const swift::Decl& decl) {
if (!llvm::isa<swift::ValueDecl>(decl)) {
return {};
}
// We do not deduplicate local variables, but for the moment also non-local vars from non-swift
// (PCM, clang modules) modules as the mangler crashes sometimes
if (decl.getKind() == swift::DeclKind::Var &&
(decl.getDeclContext()->isLocalContext() || decl.getModuleContext()->isNonSwiftModule())) {
return {};
}
// we do not deduplicate GenericTypeParamDecl, as their mangling is ambiguous in the presence of
// extensions
if (decl.getKind() == swift::DeclKind::GenericTypeParam) {
return {};
}
if (decl.getKind() == swift::DeclKind::Module) {
return mangleModuleName(llvm::cast<swift::ModuleDecl>(decl).getRealName().str());
}
auto ret = initMangled(&decl);
const auto& valueDecl = llvm::cast<swift::ValueDecl>(decl);
// stamp all declarations with an id-ref of the containing module
auto moduleLabel = dispatcher.fetchLabel(decl.getModuleContext());
ret << moduleLabel;
if (decl.getKind() == swift::DeclKind::TypeAlias) {
// In cases like this (when coming from PCM)
// typealias CFXMLTree = CFTree
// typealias CFXMLTreeRef = CFXMLTree
// mangleAnyDecl mangles both CFXMLTree and CFXMLTreeRef into 'So12CFXMLTreeRefa'
// which is not correct and causes inconsistencies. mangleEntity makes these two distinct
// prefix adds a couple of special symbols, we don't necessary need them
ret << mangler.mangleEntity(&valueDecl);
} else {
// prefix adds a couple of special symbols, we don't necessary need them
ret << mangler.mangleAnyDecl(&valueDecl, /* prefix = */ false);
}
return ret;
}
SwiftMangledName SwiftMangler::visitModuleType(const swift::ModuleType* type) {
auto ret = initMangled(type);
ret << type->getModule()->getRealName().str();
if (type->getModule()->isNonSwiftModule()) {
ret << "|clang";
}
return ret;
}
SwiftMangledName SwiftMangler::visitBuiltinType(const swift::BuiltinType* type) {
auto ret = initMangled(type);
llvm::SmallString<32> buffer;
ret << type->getTypeName(buffer, /* prependBuiltinNamespace= */ false);
return ret;
}