[Demangle] Add minimal support for D programming language

This patch adds minimal support for D programming language demangling on LLVM
core based on the D name mangling spec. This will allow easier integration on a
future LLDB plugin for D either in the upstream tree or outside of it.

Minimal support includes recognizing D demangling encoding and at least one
mangling name, which in this case is `_Dmain` mangle.

Reviewed By: jhenderson, lattner

Differential Revision: https://reviews.llvm.org/D111414
This commit is contained in:
Luís Ferreira
2021-11-09 09:04:46 -08:00
committed by David Blaikie
parent a19da876ab
commit 22a1aa5a43
8 changed files with 100 additions and 0 deletions

View File

@@ -60,6 +60,9 @@ char *microsoftDemangle(const char *mangled_name, size_t *n_read, char *buf,
// Demangles a Rust v0 mangled symbol. The API follows that of __cxa_demangle.
char *rustDemangle(const char *MangledName, char *Buf, size_t *N, int *Status);
// Demangles a D mangled symbol.
char *dlangDemangle(const char *MangledName);
/// Attempt to demangle a string using different demangling schemes.
/// The function uses heuristics to determine which demangling scheme to use.
/// \param MangledName - reference to string to demangle.

View File

@@ -4,6 +4,7 @@ add_llvm_component_library(LLVMDemangle
MicrosoftDemangle.cpp
MicrosoftDemangleNodes.cpp
RustDemangle.cpp
DLangDemangle.cpp
ADDITIONAL_HEADER_DIRS
"${LLVM_MAIN_INCLUDE_DIR}/llvm/Demangle"

View File

@@ -0,0 +1,44 @@
//===--- DLangDemangle.cpp ------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file defines a demangler for the D programming language as specified
/// in the ABI specification, available at:
/// https://dlang.org/spec/abi.html#name_mangling
///
//===----------------------------------------------------------------------===//
#include "llvm/Demangle/Demangle.h"
#include "llvm/Demangle/Utility.h"
#include <cstring>
using namespace llvm;
using llvm::itanium_demangle::OutputBuffer;
char *llvm::dlangDemangle(const char *MangledName) {
if (MangledName == nullptr || strncmp(MangledName, "_D", 2) != 0)
return nullptr;
OutputBuffer Demangled;
if (!initializeOutputBuffer(nullptr, nullptr, Demangled, 1024))
return nullptr;
if (strcmp(MangledName, "_Dmain") == 0)
Demangled << "D main";
// OutputBuffer's internal buffer is not null terminated and therefore we need
// to add it to comply with C null terminated strings.
if (Demangled.getCurrentPosition() > 0) {
Demangled << '\0';
Demangled.setCurrentPosition(Demangled.getCurrentPosition() - 1);
return Demangled.getBuffer();
}
return nullptr;
}

View File

@@ -21,6 +21,11 @@ static bool isItaniumEncoding(const char *S) {
static bool isRustEncoding(const char *S) { return S[0] == '_' && S[1] == 'R'; }
static bool isDLangEncoding(const std::string &MangledName) {
return MangledName.size() >= 2 && MangledName[0] == '_' &&
MangledName[1] == 'D';
}
std::string llvm::demangle(const std::string &MangledName) {
std::string Result;
const char *S = MangledName.c_str();
@@ -47,6 +52,8 @@ bool llvm::nonMicrosoftDemangle(const char *MangledName, std::string &Result) {
Demangled = itaniumDemangle(MangledName, nullptr, nullptr, nullptr);
else if (isRustEncoding(MangledName))
Demangled = rustDemangle(MangledName, nullptr, nullptr, nullptr);
else if (isDLangEncoding(MangledName))
Demangled = dlangDemangle(MangledName);
if (!Demangled)
return false;

View File

@@ -0,0 +1,10 @@
RUN: llvm-cxxfilt -n < %s | FileCheck --match-full-lines %s
; Full test suite for dlang demangling at
; llvm/unittests/Demangle/DLangDemangleTest.cpp
CHECK: D main
_Dmain
CHECK: _DDD
_DDD

View File

@@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(DemangleTests
DemangleTest.cpp
DLangDemangleTest.cpp
ItaniumDemangleTest.cpp
OutputBufferTest.cpp
PartialDemangleTest.cpp

View File

@@ -0,0 +1,33 @@
//===------------------ DLangDemangleTest.cpp -----------------------------===//
//
// 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 "llvm/Demangle/Demangle.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <cstdlib>
#include <utility>
struct DLangDemangleTestFixture
: public testing::TestWithParam<std::pair<const char *, const char *>> {
char *Demangled;
void SetUp() override { Demangled = llvm::dlangDemangle(GetParam().first); }
void TearDown() override { std::free(Demangled); }
};
TEST_P(DLangDemangleTestFixture, DLangDemangleTest) {
EXPECT_STREQ(Demangled, GetParam().second);
}
INSTANTIATE_TEST_SUITE_P(DLangDemangleTest, DLangDemangleTestFixture,
testing::Values(std::make_pair("_Dmain", "D main"),
std::make_pair(nullptr, nullptr),
std::make_pair("_Z", nullptr),
std::make_pair("_DDD", nullptr)));

View File

@@ -23,6 +23,7 @@ TEST(Demangle, demangleTest) {
EXPECT_EQ(demangle("foo"), "foo");
EXPECT_EQ(demangle("_RNvC3foo3bar"), "foo::bar");
EXPECT_EQ(demangle("__RNvC3foo3bar"), "foo::bar");
EXPECT_EQ(demangle("_Dmain"), "D main");
// Regression test for demangling of optional template-args for vendor
// extended type qualifier (https://bugs.llvm.org/show_bug.cgi?id=48009)