blob: 82b2494db134fd2bf90a25b15635bbb149fc947a [file] [edit]
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "DLanguage.h"
#include "lldb/Core/Mangled.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Demangle/Demangle.h"
#include <cassert>
#include <cstdlib>
using namespace lldb;
using namespace lldb_private;
LLDB_PLUGIN_DEFINE(DLanguage)
/// The mangling scheme that this plugin registered.
static Mangled::ManglingScheme g_d_scheme = Mangled::eManglingSchemeNone;
/// Returns true if \p name, which starts with "_D", is a D mangled name.
static bool IsDMangledName(llvm::StringRef name) {
// A D mangled name begins with `_D`, followed by a numeric length. One known
// exception is the symbol `_Dmain`. See `SymbolName` and `LName` in
// https://dlang.org/spec/abi.html#name_mangling
llvm::StringRef rest = name.drop_front(2);
return (!rest.empty() && llvm::isDigit(rest.front())) || name == "_Dmain";
}
void DLanguage::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(), "D Language",
CreateInstance);
g_d_scheme =
Mangled::RegisterManglingScheme({"_D"}, eLanguageTypeD, IsDMangledName);
}
void DLanguage::Terminate() {
Mangled::UnregisterManglingScheme(g_d_scheme);
PluginManager::UnregisterPlugin(CreateInstance);
}
// Static Functions
Language *DLanguage::CreateInstance(lldb::LanguageType language) {
if (language == eLanguageTypeD)
return new DLanguage();
return nullptr;
}
bool DLanguage::IsSourceFile(llvm::StringRef file_path) const {
return file_path.ends_with_insensitive(".d") ||
file_path.ends_with_insensitive(".di");
}
Language::DemangledName
DLanguage::DemangleSymbol(ConstString mangled, Mangled::ManglingScheme scheme,
const DemangleOptions &options) const {
assert(scheme == g_d_scheme);
llvm::StringRef mangled_str = mangled.GetStringRef();
char *demangled_cstr = llvm::dlangDemangle(mangled_str);
if (Log *log = GetLog(LLDBLog::Demangle)) {
if (demangled_cstr && demangled_cstr[0])
LLDB_LOG(log, "demangled dlang: {0} -> \"{1}\"", mangled_str,
demangled_cstr);
else
LLDB_LOG(log, "demangled dlang: {0} -> error: failed to demangle",
mangled_str);
}
DemangledName demangled;
if (demangled_cstr) {
demangled.name = demangled_cstr;
std::free(demangled_cstr);
}
return demangled;
}