[llvm] 22a1aa5 - [Demangle] Add minimal support for D programming language

David Blaikie via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 9 09:29:21 PST 2021


Author: Luís Ferreira
Date: 2021-11-09T09:29:13-08:00
New Revision: 22a1aa5a43cbdaf9dde014ba1f120e0f7ca1788b

URL: https://github.com/llvm/llvm-project/commit/22a1aa5a43cbdaf9dde014ba1f120e0f7ca1788b
DIFF: https://github.com/llvm/llvm-project/commit/22a1aa5a43cbdaf9dde014ba1f120e0f7ca1788b.diff

LOG: [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

Added: 
    llvm/lib/Demangle/DLangDemangle.cpp
    llvm/test/Demangle/dlang.test
    llvm/unittests/Demangle/DLangDemangleTest.cpp

Modified: 
    llvm/include/llvm/Demangle/Demangle.h
    llvm/lib/Demangle/CMakeLists.txt
    llvm/lib/Demangle/Demangle.cpp
    llvm/unittests/Demangle/CMakeLists.txt
    llvm/unittests/Demangle/DemangleTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Demangle/Demangle.h b/llvm/include/llvm/Demangle/Demangle.h
index 521795f7a1f81..3150e049320bf 100644
--- a/llvm/include/llvm/Demangle/Demangle.h
+++ b/llvm/include/llvm/Demangle/Demangle.h
@@ -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 
diff erent demangling schemes.
 /// The function uses heuristics to determine which demangling scheme to use.
 /// \param MangledName - reference to string to demangle.

diff  --git a/llvm/lib/Demangle/CMakeLists.txt b/llvm/lib/Demangle/CMakeLists.txt
index 86e2d49dddf2b..eb7d212a02449 100644
--- a/llvm/lib/Demangle/CMakeLists.txt
+++ b/llvm/lib/Demangle/CMakeLists.txt
@@ -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"

diff  --git a/llvm/lib/Demangle/DLangDemangle.cpp b/llvm/lib/Demangle/DLangDemangle.cpp
new file mode 100644
index 0000000000000..d6e8fe97982be
--- /dev/null
+++ b/llvm/lib/Demangle/DLangDemangle.cpp
@@ -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;
+}

diff  --git a/llvm/lib/Demangle/Demangle.cpp b/llvm/lib/Demangle/Demangle.cpp
index 8a1c59a4b2e54..13aa2864c183d 100644
--- a/llvm/lib/Demangle/Demangle.cpp
+++ b/llvm/lib/Demangle/Demangle.cpp
@@ -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;

diff  --git a/llvm/test/Demangle/dlang.test b/llvm/test/Demangle/dlang.test
new file mode 100644
index 0000000000000..831aa5e9a4d6e
--- /dev/null
+++ b/llvm/test/Demangle/dlang.test
@@ -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

diff  --git a/llvm/unittests/Demangle/CMakeLists.txt b/llvm/unittests/Demangle/CMakeLists.txt
index 5ee315790215e..d6071bc36bda8 100644
--- a/llvm/unittests/Demangle/CMakeLists.txt
+++ b/llvm/unittests/Demangle/CMakeLists.txt
@@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS
 
 add_llvm_unittest(DemangleTests
   DemangleTest.cpp
+  DLangDemangleTest.cpp
   ItaniumDemangleTest.cpp
   OutputBufferTest.cpp
   PartialDemangleTest.cpp

diff  --git a/llvm/unittests/Demangle/DLangDemangleTest.cpp b/llvm/unittests/Demangle/DLangDemangleTest.cpp
new file mode 100644
index 0000000000000..8a324ecd23219
--- /dev/null
+++ b/llvm/unittests/Demangle/DLangDemangleTest.cpp
@@ -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)));

diff  --git a/llvm/unittests/Demangle/DemangleTest.cpp b/llvm/unittests/Demangle/DemangleTest.cpp
index 22266752d1853..e60a75ecd76da 100644
--- a/llvm/unittests/Demangle/DemangleTest.cpp
+++ b/llvm/unittests/Demangle/DemangleTest.cpp
@@ -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)


        


More information about the llvm-commits mailing list