Skip to content

Commit cddfe5b

Browse files
andrurogerzldionne
andcommitted
[llvm] annotate interfaces in Demangle for DLL export (llvm#147564)
## Purpose This patch is one in a series of code-mods that annotate LLVM’s public interface for export. This patch annotates the `Demangle` interface with a new `DEMANGLE_ABI` annotation, which behaves like the `LLVM_ABI`. This annotation currently has no meaningful impact on the LLVM build; however, it is a prerequisite to support an LLVM Windows DLL (shared library) build. ## Overview 1. Add a new `Demangle/Visibility.h` header file that defines a new `DEMANGLE_ABI` macro. The macro resolves to the proper DLL export/import annotation on Windows and a "default" visibility annotation elsewhere. 2. Add a new `LLVM_ENABLE_DEMANGLE_EXPORT_ANNOTATIONS ` `#cmakedefine` that is used to gate the definition of `DEMANGLE_ABI`. 3. Code-mod annotate the public `Demangle` interface using the [Interface Definition Scanner (IDS)](https://github.com/compnerd/ids) tool. 4. Manually fix-up `#include` statements for consistency. 5. Format the changes with `clang-format`. 6. Add a "stub" version of `Visibility.h` under `libcxxabi/src/demangle` that always defines `DEMANGLE_ABI` to nothing. 7. Update the canonical `libcxxabi/src/demangle/ItaniumDemangle.h` instead of the llvm copy, and run `cp-to-llvm.sh` to ensure the llvm copy matches. NOTE: we rely on `ccp-to-llvm.sh` not copying `Visibillity.h` as is already the case for `DemangleConfig.h`. ## Background This PR follows the pattern established with the `llvm-c` changes made in llvm#141701. This effort is tracked in llvm#109483. Additional context is provided in [this discourse](https://discourse.llvm.org/t/psa-annotating-llvm-public-interface/85307), and documentation for `LLVM_ABI` and related annotations is found in the LLVM repo [here](https://github.com/llvm/llvm-project/blob/main/llvm/docs/InterfaceExportAnnotations.rst). ## Validation Local builds and tests to validate cross-platform compatibility. This included llvm, clang, and lldb on the following configurations: - Windows with MSVC - Windows with Clang - Linux with GCC - Linux with Clang - Darwin with Clang --------- Co-authored-by: Louis Dionne <[email protected]>
1 parent 33572eb commit cddfe5b

File tree

7 files changed

+95
-61
lines changed

7 files changed

+95
-61
lines changed

libcxxabi/src/demangle/DemangleConfig.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,8 @@
115115
#define DEMANGLE_NAMESPACE_BEGIN namespace { namespace itanium_demangle {
116116
#define DEMANGLE_NAMESPACE_END } }
117117

118+
// The DEMANGLE_ABI macro resolves to nothing when building libc++abi. Only
119+
// the llvm copy defines DEMANGLE_ABI as a visibility attribute.
120+
#define DEMANGLE_ABI
121+
118122
#endif // LIBCXXABI_DEMANGLE_DEMANGLE_CONFIG_H

libcxxabi/src/demangle/ItaniumDemangle.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3049,7 +3049,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
30493049
Node *parse(bool ParseParams = true);
30503050
};
30513051

3052-
const char* parse_discriminator(const char* first, const char* last);
3052+
DEMANGLE_ABI const char *parse_discriminator(const char *first,
3053+
const char *last);
30533054

30543055
// <name> ::= <nested-name> // N
30553056
// ::= <local-name> # See Scope Encoding below // Z

llvm/include/llvm/Demangle/Demangle.h

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLVM_DEMANGLE_DEMANGLE_H
1010
#define LLVM_DEMANGLE_DEMANGLE_H
1111

12+
#include "DemangleConfig.h"
1213
#include <cstddef>
1314
#include <optional>
1415
#include <string>
@@ -33,7 +34,8 @@ enum : int {
3334
/// Returns a non-NULL pointer to a NUL-terminated C style string
3435
/// that should be explicitly freed, if successful. Otherwise, may return
3536
/// nullptr if mangled_name is not a valid mangling or is nullptr.
36-
char *itaniumDemangle(std::string_view mangled_name, bool ParseParams = true);
37+
DEMANGLE_ABI char *itaniumDemangle(std::string_view mangled_name,
38+
bool ParseParams = true);
3739

3840
enum MSDemangleFlags {
3941
MSDF_None = 0,
@@ -52,87 +54,90 @@ enum MSDemangleFlags {
5254
/// bytes of the input string were consumed.
5355
/// status receives one of the demangle_ enum entries above if it's not nullptr.
5456
/// Flags controls various details of the demangled representation.
55-
char *microsoftDemangle(std::string_view mangled_name, size_t *n_read,
56-
int *status, MSDemangleFlags Flags = MSDF_None);
57+
DEMANGLE_ABI char *microsoftDemangle(std::string_view mangled_name,
58+
size_t *n_read, int *status,
59+
MSDemangleFlags Flags = MSDF_None);
5760

58-
std::optional<size_t>
61+
DEMANGLE_ABI std::optional<size_t>
5962
getArm64ECInsertionPointInMangledName(std::string_view MangledName);
6063

6164
// Demangles a Rust v0 mangled symbol.
62-
char *rustDemangle(std::string_view MangledName);
65+
DEMANGLE_ABI char *rustDemangle(std::string_view MangledName);
6366

6467
// Demangles a D mangled symbol.
65-
char *dlangDemangle(std::string_view MangledName);
68+
DEMANGLE_ABI char *dlangDemangle(std::string_view MangledName);
6669

6770
/// Attempt to demangle a string using different demangling schemes.
6871
/// The function uses heuristics to determine which demangling scheme to use.
6972
/// \param MangledName - reference to string to demangle.
7073
/// \returns - the demangled string, or a copy of the input string if no
7174
/// demangling occurred.
72-
std::string demangle(std::string_view MangledName);
75+
DEMANGLE_ABI std::string demangle(std::string_view MangledName);
7376

74-
bool nonMicrosoftDemangle(std::string_view MangledName, std::string &Result,
75-
bool CanHaveLeadingDot = true,
76-
bool ParseParams = true);
77+
DEMANGLE_ABI bool nonMicrosoftDemangle(std::string_view MangledName,
78+
std::string &Result,
79+
bool CanHaveLeadingDot = true,
80+
bool ParseParams = true);
7781

7882
/// "Partial" demangler. This supports demangling a string into an AST
7983
/// (typically an intermediate stage in itaniumDemangle) and querying certain
8084
/// properties or partially printing the demangled name.
8185
struct ItaniumPartialDemangler {
82-
ItaniumPartialDemangler();
86+
DEMANGLE_ABI ItaniumPartialDemangler();
8387

84-
ItaniumPartialDemangler(ItaniumPartialDemangler &&Other);
85-
ItaniumPartialDemangler &operator=(ItaniumPartialDemangler &&Other);
88+
DEMANGLE_ABI ItaniumPartialDemangler(ItaniumPartialDemangler &&Other);
89+
DEMANGLE_ABI ItaniumPartialDemangler &
90+
operator=(ItaniumPartialDemangler &&Other);
8691

8792
/// Demangle into an AST. Subsequent calls to the rest of the member functions
8893
/// implicitly operate on the AST this produces.
8994
/// \return true on error, false otherwise
90-
bool partialDemangle(const char *MangledName);
95+
DEMANGLE_ABI bool partialDemangle(const char *MangledName);
9196

9297
/// Just print the entire mangled name into Buf. Buf and N behave like the
9398
/// second and third parameters to __cxa_demangle.
94-
char *finishDemangle(char *Buf, size_t *N) const;
99+
DEMANGLE_ABI char *finishDemangle(char *Buf, size_t *N) const;
95100

96101
/// See \ref finishDemangle
97102
///
98103
/// \param[in] OB A llvm::itanium_demangle::OutputBuffer that the demangled
99104
/// name will be printed into.
100105
///
101-
char *finishDemangle(void *OB) const;
106+
DEMANGLE_ABI char *finishDemangle(void *OB) const;
102107

103108
/// Get the base name of a function. This doesn't include trailing template
104109
/// arguments, ie for "a::b<int>" this function returns "b".
105-
char *getFunctionBaseName(char *Buf, size_t *N) const;
110+
DEMANGLE_ABI char *getFunctionBaseName(char *Buf, size_t *N) const;
106111

107112
/// Get the context name for a function. For "a::b::c", this function returns
108113
/// "a::b".
109-
char *getFunctionDeclContextName(char *Buf, size_t *N) const;
114+
DEMANGLE_ABI char *getFunctionDeclContextName(char *Buf, size_t *N) const;
110115

111116
/// Get the entire name of this function.
112-
char *getFunctionName(char *Buf, size_t *N) const;
117+
DEMANGLE_ABI char *getFunctionName(char *Buf, size_t *N) const;
113118

114119
/// Get the parameters for this function.
115-
char *getFunctionParameters(char *Buf, size_t *N) const;
116-
char *getFunctionReturnType(char *Buf, size_t *N) const;
120+
DEMANGLE_ABI char *getFunctionParameters(char *Buf, size_t *N) const;
121+
DEMANGLE_ABI char *getFunctionReturnType(char *Buf, size_t *N) const;
117122

118123
/// If this function has any cv or reference qualifiers. These imply that
119124
/// the function is a non-static member function.
120-
bool hasFunctionQualifiers() const;
125+
DEMANGLE_ABI bool hasFunctionQualifiers() const;
121126

122127
/// If this symbol describes a constructor or destructor.
123-
bool isCtorOrDtor() const;
128+
DEMANGLE_ABI bool isCtorOrDtor() const;
124129

125130
/// If this symbol describes a function.
126-
bool isFunction() const;
131+
DEMANGLE_ABI bool isFunction() const;
127132

128133
/// If this symbol describes a variable.
129-
bool isData() const;
134+
DEMANGLE_ABI bool isData() const;
130135

131136
/// If this symbol is a <special-name>. These are generally implicitly
132137
/// generated by the implementation, such as vtables and typeinfo names.
133-
bool isSpecialName() const;
138+
DEMANGLE_ABI bool isSpecialName() const;
134139

135-
~ItaniumPartialDemangler();
140+
DEMANGLE_ABI ~ItaniumPartialDemangler();
136141

137142
private:
138143
void *RootNode;

llvm/include/llvm/Demangle/DemangleConfig.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,24 @@
9494
#define DEMANGLE_NAMESPACE_BEGIN namespace llvm { namespace itanium_demangle {
9595
#define DEMANGLE_NAMESPACE_END } }
9696

97+
/// DEMANGLE_ABI is the export/visibility macro used to mark symbols delcared in
98+
/// llvm/Demangle as exported when built as a shared library.
99+
#if defined(LLVM_BUILD_STATIC) || !defined(LLVM_ENABLE_LLVM_EXPORT_ANNOTATIONS)
100+
#define DEMANGLE_ABI
101+
#else
102+
#if defined(_WIN32)
103+
#if defined(LLVM_EXPORTS)
104+
#define DEMANGLE_ABI __declspec(dllexport)
105+
#else
106+
#define DEMANGLE_ABI__declspec(dllimport)
107+
#endif
108+
#else
109+
#if __has_attribute(visibility)
110+
#define DEMANGLE_ABI __attribute__((__visibility__("default")))
111+
#else
112+
#define DEMANGLE_ABI
113+
#endif
114+
#endif
115+
#endif
116+
97117
#endif

llvm/include/llvm/Demangle/ItaniumDemangle.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3049,7 +3049,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
30493049
Node *parse(bool ParseParams = true);
30503050
};
30513051

3052-
const char* parse_discriminator(const char* first, const char* last);
3052+
DEMANGLE_ABI const char *parse_discriminator(const char *first,
3053+
const char *last);
30533054

30543055
// <name> ::= <nested-name> // N
30553056
// ::= <local-name> # See Scope Encoding below // Z

llvm/include/llvm/Demangle/MicrosoftDemangle.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLVM_DEMANGLE_MICROSOFTDEMANGLE_H
1111

1212
#include "llvm/Demangle/Demangle.h"
13+
#include "llvm/Demangle/DemangleConfig.h"
1314
#include "llvm/Demangle/MicrosoftDemangleNodes.h"
1415

1516
#include <cassert>
@@ -151,14 +152,14 @@ class Demangler {
151152

152153
// You are supposed to call parse() first and then check if error is true. If
153154
// it is false, call output() to write the formatted name to the given stream.
154-
SymbolNode *parse(std::string_view &MangledName);
155+
DEMANGLE_ABI SymbolNode *parse(std::string_view &MangledName);
155156

156-
TagTypeNode *parseTagUniqueName(std::string_view &MangledName);
157+
DEMANGLE_ABI TagTypeNode *parseTagUniqueName(std::string_view &MangledName);
157158

158159
// True if an error occurred.
159160
bool Error = false;
160161

161-
void dumpBackReferences();
162+
DEMANGLE_ABI void dumpBackReferences();
162163

163164
private:
164165
SymbolNode *demangleEncodedSymbol(std::string_view &MangledName,

0 commit comments

Comments
 (0)