Skip to content

Commit 22a1aa5

Browse files
ljmf00dwblaikie
authored andcommitted
[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
1 parent a19da87 commit 22a1aa5

File tree

8 files changed

+100
-0
lines changed

8 files changed

+100
-0
lines changed

llvm/include/llvm/Demangle/Demangle.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ char *microsoftDemangle(const char *mangled_name, size_t *n_read, char *buf,
6060
// Demangles a Rust v0 mangled symbol. The API follows that of __cxa_demangle.
6161
char *rustDemangle(const char *MangledName, char *Buf, size_t *N, int *Status);
6262

63+
// Demangles a D mangled symbol.
64+
char *dlangDemangle(const char *MangledName);
65+
6366
/// Attempt to demangle a string using different demangling schemes.
6467
/// The function uses heuristics to determine which demangling scheme to use.
6568
/// \param MangledName - reference to string to demangle.

llvm/lib/Demangle/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ add_llvm_component_library(LLVMDemangle
44
MicrosoftDemangle.cpp
55
MicrosoftDemangleNodes.cpp
66
RustDemangle.cpp
7+
DLangDemangle.cpp
78

89
ADDITIONAL_HEADER_DIRS
910
"${LLVM_MAIN_INCLUDE_DIR}/llvm/Demangle"

llvm/lib/Demangle/DLangDemangle.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//===--- DLangDemangle.cpp ------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
///
9+
/// \file
10+
/// This file defines a demangler for the D programming language as specified
11+
/// in the ABI specification, available at:
12+
/// https://dlang.org/spec/abi.html#name_mangling
13+
///
14+
//===----------------------------------------------------------------------===//
15+
16+
#include "llvm/Demangle/Demangle.h"
17+
#include "llvm/Demangle/Utility.h"
18+
19+
#include <cstring>
20+
21+
using namespace llvm;
22+
using llvm::itanium_demangle::OutputBuffer;
23+
24+
char *llvm::dlangDemangle(const char *MangledName) {
25+
if (MangledName == nullptr || strncmp(MangledName, "_D", 2) != 0)
26+
return nullptr;
27+
28+
OutputBuffer Demangled;
29+
if (!initializeOutputBuffer(nullptr, nullptr, Demangled, 1024))
30+
return nullptr;
31+
32+
if (strcmp(MangledName, "_Dmain") == 0)
33+
Demangled << "D main";
34+
35+
// OutputBuffer's internal buffer is not null terminated and therefore we need
36+
// to add it to comply with C null terminated strings.
37+
if (Demangled.getCurrentPosition() > 0) {
38+
Demangled << '\0';
39+
Demangled.setCurrentPosition(Demangled.getCurrentPosition() - 1);
40+
return Demangled.getBuffer();
41+
}
42+
43+
return nullptr;
44+
}

llvm/lib/Demangle/Demangle.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ static bool isItaniumEncoding(const char *S) {
2121

2222
static bool isRustEncoding(const char *S) { return S[0] == '_' && S[1] == 'R'; }
2323

24+
static bool isDLangEncoding(const std::string &MangledName) {
25+
return MangledName.size() >= 2 && MangledName[0] == '_' &&
26+
MangledName[1] == 'D';
27+
}
28+
2429
std::string llvm::demangle(const std::string &MangledName) {
2530
std::string Result;
2631
const char *S = MangledName.c_str();
@@ -47,6 +52,8 @@ bool llvm::nonMicrosoftDemangle(const char *MangledName, std::string &Result) {
4752
Demangled = itaniumDemangle(MangledName, nullptr, nullptr, nullptr);
4853
else if (isRustEncoding(MangledName))
4954
Demangled = rustDemangle(MangledName, nullptr, nullptr, nullptr);
55+
else if (isDLangEncoding(MangledName))
56+
Demangled = dlangDemangle(MangledName);
5057

5158
if (!Demangled)
5259
return false;

llvm/test/Demangle/dlang.test

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
RUN: llvm-cxxfilt -n < %s | FileCheck --match-full-lines %s
2+
3+
; Full test suite for dlang demangling at
4+
; llvm/unittests/Demangle/DLangDemangleTest.cpp
5+
6+
CHECK: D main
7+
_Dmain
8+
9+
CHECK: _DDD
10+
_DDD

llvm/unittests/Demangle/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS
55

66
add_llvm_unittest(DemangleTests
77
DemangleTest.cpp
8+
DLangDemangleTest.cpp
89
ItaniumDemangleTest.cpp
910
OutputBufferTest.cpp
1011
PartialDemangleTest.cpp
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===------------------ DLangDemangleTest.cpp -----------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/Demangle/Demangle.h"
10+
#include "gmock/gmock.h"
11+
#include "gtest/gtest.h"
12+
13+
#include <cstdlib>
14+
#include <utility>
15+
16+
struct DLangDemangleTestFixture
17+
: public testing::TestWithParam<std::pair<const char *, const char *>> {
18+
char *Demangled;
19+
20+
void SetUp() override { Demangled = llvm::dlangDemangle(GetParam().first); }
21+
22+
void TearDown() override { std::free(Demangled); }
23+
};
24+
25+
TEST_P(DLangDemangleTestFixture, DLangDemangleTest) {
26+
EXPECT_STREQ(Demangled, GetParam().second);
27+
}
28+
29+
INSTANTIATE_TEST_SUITE_P(DLangDemangleTest, DLangDemangleTestFixture,
30+
testing::Values(std::make_pair("_Dmain", "D main"),
31+
std::make_pair(nullptr, nullptr),
32+
std::make_pair("_Z", nullptr),
33+
std::make_pair("_DDD", nullptr)));

llvm/unittests/Demangle/DemangleTest.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ TEST(Demangle, demangleTest) {
2323
EXPECT_EQ(demangle("foo"), "foo");
2424
EXPECT_EQ(demangle("_RNvC3foo3bar"), "foo::bar");
2525
EXPECT_EQ(demangle("__RNvC3foo3bar"), "foo::bar");
26+
EXPECT_EQ(demangle("_Dmain"), "D main");
2627

2728
// Regression test for demangling of optional template-args for vendor
2829
// extended type qualifier (https://bugs.llvm.org/show_bug.cgi?id=48009)

0 commit comments

Comments
 (0)