[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:
committed by
David Blaikie
parent
a19da876ab
commit
22a1aa5a43
@@ -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.
|
||||
|
||||
@@ -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"
|
||||
|
||||
44
llvm/lib/Demangle/DLangDemangle.cpp
Normal file
44
llvm/lib/Demangle/DLangDemangle.cpp
Normal 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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
10
llvm/test/Demangle/dlang.test
Normal file
10
llvm/test/Demangle/dlang.test
Normal 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
|
||||
@@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS
|
||||
|
||||
add_llvm_unittest(DemangleTests
|
||||
DemangleTest.cpp
|
||||
DLangDemangleTest.cpp
|
||||
ItaniumDemangleTest.cpp
|
||||
OutputBufferTest.cpp
|
||||
PartialDemangleTest.cpp
|
||||
|
||||
33
llvm/unittests/Demangle/DLangDemangleTest.cpp
Normal file
33
llvm/unittests/Demangle/DLangDemangleTest.cpp
Normal 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)));
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user