sys: Updated llvm demangler, now supports D-Lang and Rust symbols
This commit is contained in:
parent
f1ec2ef0c4
commit
0192c791ce
15
lib/external/llvm-demangle/CMakeLists.txt
vendored
Normal file
15
lib/external/llvm-demangle/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(llvm-demangle)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
add_library(llvm-demangle STATIC
|
||||
source/Demangle.cpp
|
||||
source/DLangDemangle.cpp
|
||||
source/ItaniumDemangle.cpp
|
||||
source/MicrosoftDemangle.cpp
|
||||
source/MicrosoftDemangleNodes.cpp
|
||||
source/RustDemangle.cpp
|
||||
)
|
||||
|
||||
target_include_directories(llvm-demangle PUBLIC include)
|
279
lib/external/llvm-demangle/LICENSE.TXT
vendored
Normal file
279
lib/external/llvm-demangle/LICENSE.TXT
vendored
Normal file
@ -0,0 +1,279 @@
|
||||
==============================================================================
|
||||
The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
|
||||
==============================================================================
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
---- LLVM Exceptions to the Apache 2.0 License ----
|
||||
|
||||
As an exception, if, as a result of your compiling your source code, portions
|
||||
of this Software are embedded into an Object form of such source code, you
|
||||
may redistribute such embedded portions in such Object form without complying
|
||||
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
|
||||
|
||||
In addition, if you combine or link compiled forms of this Software with
|
||||
software that is licensed under the GPLv2 ("Combined Software") and if a
|
||||
court of competent jurisdiction determines that the patent provision (Section
|
||||
3), the indemnity provision (Section 9) or other Section of the License
|
||||
conflicts with the conditions of the GPLv2, you may retroactively and
|
||||
prospectively choose to deem waived or otherwise exclude such Section(s) of
|
||||
the License, but only in their entirety and only with respect to the Combined
|
||||
Software.
|
||||
|
||||
==============================================================================
|
||||
Software from third parties included in the LLVM Project:
|
||||
==============================================================================
|
||||
The LLVM Project contains third party software which is under different license
|
||||
terms. All such code will be identified clearly using at least one of two
|
||||
mechanisms:
|
||||
1) It will be in a separate directory tree with its own `LICENSE.txt` or
|
||||
`LICENSE` file at the top containing the specific license and restrictions
|
||||
which apply to that software, or
|
||||
2) It will contain specific license and restriction terms at the top of every
|
||||
file.
|
||||
|
||||
==============================================================================
|
||||
Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
|
||||
==============================================================================
|
||||
University of Illinois/NCSA
|
||||
Open Source License
|
||||
|
||||
Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign.
|
||||
All rights reserved.
|
||||
|
||||
Developed by:
|
||||
|
||||
LLVM Team
|
||||
|
||||
University of Illinois at Urbana-Champaign
|
||||
|
||||
http://llvm.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal with
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimers.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimers in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the names of the LLVM Team, University of Illinois at
|
||||
Urbana-Champaign, nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this Software without specific
|
||||
prior written permission.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
|
||||
SOFTWARE.
|
||||
|
@ -31,7 +31,6 @@ enum : int {
|
||||
char *itaniumDemangle(const char *mangled_name, char *buf, size_t *n,
|
||||
int *status);
|
||||
|
||||
|
||||
enum MSDemangleFlags {
|
||||
MSDF_None = 0,
|
||||
MSDF_DumpBackrefs = 1 << 0,
|
||||
@ -39,6 +38,7 @@ enum MSDemangleFlags {
|
||||
MSDF_NoCallingConvention = 1 << 2,
|
||||
MSDF_NoReturnType = 1 << 3,
|
||||
MSDF_NoMemberType = 1 << 4,
|
||||
MSDF_NoVariableType = 1 << 5,
|
||||
};
|
||||
|
||||
/// Demangles the Microsoft symbol pointed at by mangled_name and returns it.
|
||||
@ -53,9 +53,15 @@ enum MSDemangleFlags {
|
||||
/// receives the size of the demangled string on output if n_buf is not nullptr.
|
||||
/// status receives one of the demangle_ enum entries above if it's not nullptr.
|
||||
/// Flags controls various details of the demangled representation.
|
||||
char *microsoftDemangle(const char *mangled_name, size_t *n_read,
|
||||
char *buf, size_t *n_buf,
|
||||
int *status, MSDemangleFlags Flags = MSDF_None);
|
||||
char *microsoftDemangle(const char *mangled_name, size_t *n_read, char *buf,
|
||||
size_t *n_buf, int *status,
|
||||
MSDemangleFlags Flags = MSDF_None);
|
||||
|
||||
// Demangles a Rust v0 mangled symbol.
|
||||
char *rustDemangle(const char *MangledName);
|
||||
|
||||
// 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.
|
||||
@ -64,6 +70,8 @@ char *microsoftDemangle(const char *mangled_name, size_t *n_read,
|
||||
/// demangling occurred.
|
||||
std::string demangle(const std::string &MangledName);
|
||||
|
||||
bool nonMicrosoftDemangle(const char *MangledName, std::string &Result);
|
||||
|
||||
/// "Partial" demangler. This supports demangling a string into an AST
|
||||
/// (typically an intermediate stage in itaniumDemangle) and querying certain
|
||||
/// properties or partially printing the demangled name.
|
||||
@ -115,6 +123,7 @@ struct ItaniumPartialDemangler {
|
||||
bool isSpecialName() const;
|
||||
|
||||
~ItaniumPartialDemangler();
|
||||
|
||||
private:
|
||||
void *RootNode;
|
||||
void *Context;
|
@ -12,8 +12,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_DEMANGLE_COMPILER_H
|
||||
#define LLVM_DEMANGLE_COMPILER_H
|
||||
#ifndef LLVM_DEMANGLE_DEMANGLECONFIG_H
|
||||
#define LLVM_DEMANGLE_DEMANGLECONFIG_H
|
||||
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0
|
File diff suppressed because it is too large
Load Diff
95
lib/external/llvm-demangle/include/llvm/Demangle/ItaniumNodes.def
vendored
Normal file
95
lib/external/llvm-demangle/include/llvm/Demangle/ItaniumNodes.def
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
//===--- ItaniumNodes.def ------------*- mode:c++;eval:(read-only-mode) -*-===//
|
||||
// Do not edit! See README.txt.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Define the demangler's node names
|
||||
|
||||
#ifndef NODE
|
||||
#error Define NODE to handle nodes
|
||||
#endif
|
||||
|
||||
NODE(NodeArrayNode)
|
||||
NODE(DotSuffix)
|
||||
NODE(VendorExtQualType)
|
||||
NODE(QualType)
|
||||
NODE(ConversionOperatorType)
|
||||
NODE(PostfixQualifiedType)
|
||||
NODE(ElaboratedTypeSpefType)
|
||||
NODE(NameType)
|
||||
NODE(AbiTagAttr)
|
||||
NODE(EnableIfAttr)
|
||||
NODE(ObjCProtoName)
|
||||
NODE(PointerType)
|
||||
NODE(ReferenceType)
|
||||
NODE(PointerToMemberType)
|
||||
NODE(ArrayType)
|
||||
NODE(FunctionType)
|
||||
NODE(NoexceptSpec)
|
||||
NODE(DynamicExceptionSpec)
|
||||
NODE(FunctionEncoding)
|
||||
NODE(LiteralOperator)
|
||||
NODE(SpecialName)
|
||||
NODE(CtorVtableSpecialName)
|
||||
NODE(QualifiedName)
|
||||
NODE(NestedName)
|
||||
NODE(LocalName)
|
||||
NODE(ModuleName)
|
||||
NODE(ModuleEntity)
|
||||
NODE(VectorType)
|
||||
NODE(PixelVectorType)
|
||||
NODE(BinaryFPType)
|
||||
NODE(BitIntType)
|
||||
NODE(SyntheticTemplateParamName)
|
||||
NODE(TypeTemplateParamDecl)
|
||||
NODE(NonTypeTemplateParamDecl)
|
||||
NODE(TemplateTemplateParamDecl)
|
||||
NODE(TemplateParamPackDecl)
|
||||
NODE(ParameterPack)
|
||||
NODE(TemplateArgumentPack)
|
||||
NODE(ParameterPackExpansion)
|
||||
NODE(TemplateArgs)
|
||||
NODE(ForwardTemplateReference)
|
||||
NODE(NameWithTemplateArgs)
|
||||
NODE(GlobalQualifiedName)
|
||||
NODE(ExpandedSpecialSubstitution)
|
||||
NODE(SpecialSubstitution)
|
||||
NODE(CtorDtorName)
|
||||
NODE(DtorName)
|
||||
NODE(UnnamedTypeName)
|
||||
NODE(ClosureTypeName)
|
||||
NODE(StructuredBindingName)
|
||||
NODE(BinaryExpr)
|
||||
NODE(ArraySubscriptExpr)
|
||||
NODE(PostfixExpr)
|
||||
NODE(ConditionalExpr)
|
||||
NODE(MemberExpr)
|
||||
NODE(SubobjectExpr)
|
||||
NODE(EnclosingExpr)
|
||||
NODE(CastExpr)
|
||||
NODE(SizeofParamPackExpr)
|
||||
NODE(CallExpr)
|
||||
NODE(NewExpr)
|
||||
NODE(DeleteExpr)
|
||||
NODE(PrefixExpr)
|
||||
NODE(FunctionParam)
|
||||
NODE(ConversionExpr)
|
||||
NODE(PointerToMemberConversionExpr)
|
||||
NODE(InitListExpr)
|
||||
NODE(FoldExpr)
|
||||
NODE(ThrowExpr)
|
||||
NODE(BoolExpr)
|
||||
NODE(StringLiteral)
|
||||
NODE(LambdaExpr)
|
||||
NODE(EnumLiteral)
|
||||
NODE(IntegerLiteral)
|
||||
NODE(FloatLiteral)
|
||||
NODE(DoubleLiteral)
|
||||
NODE(LongDoubleLiteral)
|
||||
NODE(BracedExpr)
|
||||
NODE(BracedRangeExpr)
|
||||
|
||||
#undef NODE
|
@ -6,13 +6,11 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_DEMANGLE_MICROSOFT_DEMANGLE_H
|
||||
#define LLVM_DEMANGLE_MICROSOFT_DEMANGLE_H
|
||||
#ifndef LLVM_DEMANGLE_MICROSOFTDEMANGLE_H
|
||||
#define LLVM_DEMANGLE_MICROSOFTDEMANGLE_H
|
||||
|
||||
#include "llvm/Demangle/DemangleConfig.h"
|
||||
#include "llvm/Demangle/MicrosoftDemangleNodes.h"
|
||||
#include "llvm/Demangle/StringView.h"
|
||||
#include "llvm/Demangle/Utility.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
@ -275,4 +273,4 @@ private:
|
||||
} // namespace ms_demangle
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_DEMANGLE_MICROSOFT_DEMANGLE_H
|
||||
#endif // LLVM_DEMANGLE_MICROSOFTDEMANGLE_H
|
@ -10,10 +10,9 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_SUPPORT_MICROSOFTDEMANGLENODES_H
|
||||
#define LLVM_SUPPORT_MICROSOFTDEMANGLENODES_H
|
||||
#ifndef LLVM_DEMANGLE_MICROSOFTDEMANGLENODES_H
|
||||
#define LLVM_DEMANGLE_MICROSOFTDEMANGLENODES_H
|
||||
|
||||
#include "llvm/Demangle/DemangleConfig.h"
|
||||
#include "llvm/Demangle/StringView.h"
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
@ -21,11 +20,11 @@
|
||||
|
||||
namespace llvm {
|
||||
namespace itanium_demangle {
|
||||
class OutputStream;
|
||||
class OutputBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
using llvm::itanium_demangle::OutputStream;
|
||||
using llvm::itanium_demangle::OutputBuffer;
|
||||
using llvm::itanium_demangle::StringView;
|
||||
|
||||
namespace llvm {
|
||||
@ -67,6 +66,8 @@ enum class CallingConv : uint8_t {
|
||||
Eabi,
|
||||
Vectorcall,
|
||||
Regcall,
|
||||
Swift, // Clang-only
|
||||
SwiftAsync, // Clang-only
|
||||
};
|
||||
|
||||
enum class ReferenceKind : uint8_t { None, LValueRef, RValueRef };
|
||||
@ -78,6 +79,7 @@ enum OutputFlags {
|
||||
OF_NoAccessSpecifier = 4,
|
||||
OF_NoMemberType = 8,
|
||||
OF_NoReturnType = 16,
|
||||
OF_NoVariableType = 32,
|
||||
};
|
||||
|
||||
// Types
|
||||
@ -259,7 +261,7 @@ struct Node {
|
||||
|
||||
NodeKind kind() const { return Kind; }
|
||||
|
||||
virtual void output(OutputStream &OS, OutputFlags Flags) const = 0;
|
||||
virtual void output(OutputBuffer &OB, OutputFlags Flags) const = 0;
|
||||
|
||||
std::string toString(OutputFlags Flags = OF_Default) const;
|
||||
|
||||
@ -280,9 +282,7 @@ struct StructorIdentifierNode;
|
||||
struct ThunkSignatureNode;
|
||||
struct PointerTypeNode;
|
||||
struct ArrayTypeNode;
|
||||
struct CustomNode;
|
||||
struct TagTypeNode;
|
||||
struct IntrinsicTypeNode;
|
||||
struct NodeArrayNode;
|
||||
struct QualifiedNameNode;
|
||||
struct TemplateParameterReferenceNode;
|
||||
@ -298,12 +298,12 @@ struct SpecialTableSymbolNode;
|
||||
struct TypeNode : public Node {
|
||||
explicit TypeNode(NodeKind K) : Node(K) {}
|
||||
|
||||
virtual void outputPre(OutputStream &OS, OutputFlags Flags) const = 0;
|
||||
virtual void outputPost(OutputStream &OS, OutputFlags Flags) const = 0;
|
||||
virtual void outputPre(OutputBuffer &OB, OutputFlags Flags) const = 0;
|
||||
virtual void outputPost(OutputBuffer &OB, OutputFlags Flags) const = 0;
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override {
|
||||
outputPre(OS, Flags);
|
||||
outputPost(OS, Flags);
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override {
|
||||
outputPre(OB, Flags);
|
||||
outputPost(OB, Flags);
|
||||
}
|
||||
|
||||
Qualifiers Quals = Q_None;
|
||||
@ -313,8 +313,8 @@ struct PrimitiveTypeNode : public TypeNode {
|
||||
explicit PrimitiveTypeNode(PrimitiveKind K)
|
||||
: TypeNode(NodeKind::PrimitiveType), PrimKind(K) {}
|
||||
|
||||
void outputPre(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void outputPost(OutputStream &OS, OutputFlags Flags) const override {}
|
||||
void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
void outputPost(OutputBuffer &OB, OutputFlags Flags) const override {}
|
||||
|
||||
PrimitiveKind PrimKind;
|
||||
};
|
||||
@ -323,8 +323,8 @@ struct FunctionSignatureNode : public TypeNode {
|
||||
explicit FunctionSignatureNode(NodeKind K) : TypeNode(K) {}
|
||||
FunctionSignatureNode() : TypeNode(NodeKind::FunctionSignature) {}
|
||||
|
||||
void outputPre(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void outputPost(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
// Valid if this FunctionTypeNode is the Pointee of a PointerType or
|
||||
// MemberPointerType.
|
||||
@ -357,13 +357,13 @@ struct IdentifierNode : public Node {
|
||||
NodeArrayNode *TemplateParams = nullptr;
|
||||
|
||||
protected:
|
||||
void outputTemplateParameters(OutputStream &OS, OutputFlags Flags) const;
|
||||
void outputTemplateParameters(OutputBuffer &OB, OutputFlags Flags) const;
|
||||
};
|
||||
|
||||
struct VcallThunkIdentifierNode : public IdentifierNode {
|
||||
VcallThunkIdentifierNode() : IdentifierNode(NodeKind::VcallThunkIdentifier) {}
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
uint64_t OffsetInVTable = 0;
|
||||
};
|
||||
@ -372,7 +372,7 @@ struct DynamicStructorIdentifierNode : public IdentifierNode {
|
||||
DynamicStructorIdentifierNode()
|
||||
: IdentifierNode(NodeKind::DynamicStructorIdentifier) {}
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
VariableSymbolNode *Variable = nullptr;
|
||||
QualifiedNameNode *Name = nullptr;
|
||||
@ -382,7 +382,7 @@ struct DynamicStructorIdentifierNode : public IdentifierNode {
|
||||
struct NamedIdentifierNode : public IdentifierNode {
|
||||
NamedIdentifierNode() : IdentifierNode(NodeKind::NamedIdentifier) {}
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
StringView Name;
|
||||
};
|
||||
@ -392,7 +392,7 @@ struct IntrinsicFunctionIdentifierNode : public IdentifierNode {
|
||||
: IdentifierNode(NodeKind::IntrinsicFunctionIdentifier),
|
||||
Operator(Operator) {}
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
IntrinsicFunctionKind Operator;
|
||||
};
|
||||
@ -401,7 +401,7 @@ struct LiteralOperatorIdentifierNode : public IdentifierNode {
|
||||
LiteralOperatorIdentifierNode()
|
||||
: IdentifierNode(NodeKind::LiteralOperatorIdentifier) {}
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
StringView Name;
|
||||
};
|
||||
@ -410,7 +410,7 @@ struct LocalStaticGuardIdentifierNode : public IdentifierNode {
|
||||
LocalStaticGuardIdentifierNode()
|
||||
: IdentifierNode(NodeKind::LocalStaticGuardIdentifier) {}
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
bool IsThread = false;
|
||||
uint32_t ScopeIndex = 0;
|
||||
@ -420,7 +420,7 @@ struct ConversionOperatorIdentifierNode : public IdentifierNode {
|
||||
ConversionOperatorIdentifierNode()
|
||||
: IdentifierNode(NodeKind::ConversionOperatorIdentifier) {}
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
// The type that this operator converts too.
|
||||
TypeNode *TargetType = nullptr;
|
||||
@ -432,7 +432,7 @@ struct StructorIdentifierNode : public IdentifierNode {
|
||||
: IdentifierNode(NodeKind::StructorIdentifier),
|
||||
IsDestructor(IsDestructor) {}
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
// The name of the class that this is a structor of.
|
||||
IdentifierNode *Class = nullptr;
|
||||
@ -442,8 +442,8 @@ struct StructorIdentifierNode : public IdentifierNode {
|
||||
struct ThunkSignatureNode : public FunctionSignatureNode {
|
||||
ThunkSignatureNode() : FunctionSignatureNode(NodeKind::ThunkSignature) {}
|
||||
|
||||
void outputPre(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void outputPost(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
struct ThisAdjustor {
|
||||
uint32_t StaticOffset = 0;
|
||||
@ -457,8 +457,8 @@ struct ThunkSignatureNode : public FunctionSignatureNode {
|
||||
|
||||
struct PointerTypeNode : public TypeNode {
|
||||
PointerTypeNode() : TypeNode(NodeKind::PointerType) {}
|
||||
void outputPre(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void outputPost(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
// Is this a pointer, reference, or rvalue-reference?
|
||||
PointerAffinity Affinity = PointerAffinity::None;
|
||||
@ -474,8 +474,8 @@ struct PointerTypeNode : public TypeNode {
|
||||
struct TagTypeNode : public TypeNode {
|
||||
explicit TagTypeNode(TagKind Tag) : TypeNode(NodeKind::TagType), Tag(Tag) {}
|
||||
|
||||
void outputPre(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void outputPost(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
QualifiedNameNode *QualifiedName = nullptr;
|
||||
TagKind Tag;
|
||||
@ -484,11 +484,11 @@ struct TagTypeNode : public TypeNode {
|
||||
struct ArrayTypeNode : public TypeNode {
|
||||
ArrayTypeNode() : TypeNode(NodeKind::ArrayType) {}
|
||||
|
||||
void outputPre(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void outputPost(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
void outputDimensionsImpl(OutputStream &OS, OutputFlags Flags) const;
|
||||
void outputOneDimension(OutputStream &OS, OutputFlags Flags, Node *N) const;
|
||||
void outputDimensionsImpl(OutputBuffer &OB, OutputFlags Flags) const;
|
||||
void outputOneDimension(OutputBuffer &OB, OutputFlags Flags, Node *N) const;
|
||||
|
||||
// A list of array dimensions. e.g. [3,4,5] in `int Foo[3][4][5]`
|
||||
NodeArrayNode *Dimensions = nullptr;
|
||||
@ -499,14 +499,14 @@ struct ArrayTypeNode : public TypeNode {
|
||||
|
||||
struct IntrinsicNode : public TypeNode {
|
||||
IntrinsicNode() : TypeNode(NodeKind::IntrinsicType) {}
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override {}
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override {}
|
||||
};
|
||||
|
||||
struct CustomTypeNode : public TypeNode {
|
||||
CustomTypeNode() : TypeNode(NodeKind::Custom) {}
|
||||
|
||||
void outputPre(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void outputPost(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
IdentifierNode *Identifier = nullptr;
|
||||
};
|
||||
@ -514,9 +514,9 @@ struct CustomTypeNode : public TypeNode {
|
||||
struct NodeArrayNode : public Node {
|
||||
NodeArrayNode() : Node(NodeKind::NodeArray) {}
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags, StringView Separator) const;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags, StringView Separator) const;
|
||||
|
||||
Node **Nodes = nullptr;
|
||||
size_t Count = 0;
|
||||
@ -525,7 +525,7 @@ struct NodeArrayNode : public Node {
|
||||
struct QualifiedNameNode : public Node {
|
||||
QualifiedNameNode() : Node(NodeKind::QualifiedName) {}
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
NodeArrayNode *Components = nullptr;
|
||||
|
||||
@ -539,7 +539,7 @@ struct TemplateParameterReferenceNode : public Node {
|
||||
TemplateParameterReferenceNode()
|
||||
: Node(NodeKind::TemplateParameterReference) {}
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
SymbolNode *Symbol = nullptr;
|
||||
|
||||
@ -554,7 +554,7 @@ struct IntegerLiteralNode : public Node {
|
||||
IntegerLiteralNode(uint64_t Value, bool IsNegative)
|
||||
: Node(NodeKind::IntegerLiteral), Value(Value), IsNegative(IsNegative) {}
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
uint64_t Value = 0;
|
||||
bool IsNegative = false;
|
||||
@ -564,7 +564,7 @@ struct RttiBaseClassDescriptorNode : public IdentifierNode {
|
||||
RttiBaseClassDescriptorNode()
|
||||
: IdentifierNode(NodeKind::RttiBaseClassDescriptor) {}
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
uint32_t NVOffset = 0;
|
||||
int32_t VBPtrOffset = 0;
|
||||
@ -574,7 +574,7 @@ struct RttiBaseClassDescriptorNode : public IdentifierNode {
|
||||
|
||||
struct SymbolNode : public Node {
|
||||
explicit SymbolNode(NodeKind K) : Node(K) {}
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
QualifiedNameNode *Name = nullptr;
|
||||
};
|
||||
|
||||
@ -582,7 +582,7 @@ struct SpecialTableSymbolNode : public SymbolNode {
|
||||
explicit SpecialTableSymbolNode()
|
||||
: SymbolNode(NodeKind::SpecialTableSymbol) {}
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
QualifiedNameNode *TargetName = nullptr;
|
||||
Qualifiers Quals = Qualifiers::Q_None;
|
||||
};
|
||||
@ -591,7 +591,7 @@ struct LocalStaticGuardVariableNode : public SymbolNode {
|
||||
LocalStaticGuardVariableNode()
|
||||
: SymbolNode(NodeKind::LocalStaticGuardVariable) {}
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
bool IsVisible = false;
|
||||
};
|
||||
@ -599,7 +599,7 @@ struct LocalStaticGuardVariableNode : public SymbolNode {
|
||||
struct EncodedStringLiteralNode : public SymbolNode {
|
||||
EncodedStringLiteralNode() : SymbolNode(NodeKind::EncodedStringLiteral) {}
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
StringView DecodedString;
|
||||
bool IsTruncated = false;
|
||||
@ -609,7 +609,7 @@ struct EncodedStringLiteralNode : public SymbolNode {
|
||||
struct VariableSymbolNode : public SymbolNode {
|
||||
VariableSymbolNode() : SymbolNode(NodeKind::VariableSymbol) {}
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
StorageClass SC = StorageClass::None;
|
||||
TypeNode *Type = nullptr;
|
||||
@ -618,7 +618,7 @@ struct VariableSymbolNode : public SymbolNode {
|
||||
struct FunctionSymbolNode : public SymbolNode {
|
||||
FunctionSymbolNode() : SymbolNode(NodeKind::FunctionSymbol) {}
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void output(OutputBuffer &OB, OutputFlags Flags) const override;
|
||||
|
||||
FunctionSignatureNode *Signature = nullptr;
|
||||
};
|
61
lib/external/llvm-demangle/include/llvm/Demangle/README.txt
vendored
Normal file
61
lib/external/llvm-demangle/include/llvm/Demangle/README.txt
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
Itanium Name Demangler Library
|
||||
==============================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
This directory contains the generic itanium name demangler
|
||||
library. The main purpose of the library is to demangle C++ symbols,
|
||||
i.e. convert the string "_Z1fv" into "f()". You can also use the CRTP
|
||||
base ManglingParser to perform some simple analysis on the mangled
|
||||
name, or (in LLVM) use the opaque ItaniumPartialDemangler to query the
|
||||
demangled AST.
|
||||
|
||||
Why are there multiple copies of the this library in the source tree?
|
||||
---------------------------------------------------------------------
|
||||
|
||||
The canonical sources are in libcxxabi/src/demangle and some of the
|
||||
files are copied to llvm/include/llvm/Demangle. The simple reason for
|
||||
this comes from before the monorepo, and both [sub]projects need to
|
||||
demangle symbols, but neither can depend on each other.
|
||||
|
||||
* libcxxabi needs the demangler to implement __cxa_demangle, which is
|
||||
part of the itanium ABI spec.
|
||||
|
||||
* LLVM needs a copy for a bunch of places, and cannot rely on the
|
||||
system's __cxa_demangle because it a) might not be available (i.e.,
|
||||
on Windows), and b) may not be up-to-date on the latest language
|
||||
features.
|
||||
|
||||
The copy of the demangler in LLVM has some extra stuff that aren't
|
||||
needed in libcxxabi (ie, the MSVC demangler, ItaniumPartialDemangler),
|
||||
which depend on the shared generic components. Despite these
|
||||
differences, we want to keep the "core" generic demangling library
|
||||
identical between both copies to simplify development and testing.
|
||||
|
||||
If you're working on the generic library, then do the work first in
|
||||
libcxxabi, then run the cp-to-llvm.sh script in src/demangle. This
|
||||
script takes as an optional argument the path to llvm, and copies the
|
||||
changes you made to libcxxabi over. Note that this script just
|
||||
blindly overwrites all changes to the generic library in llvm, so be
|
||||
careful.
|
||||
|
||||
Because the core demangler needs to work in libcxxabi, everything
|
||||
needs to be declared in an anonymous namespace (see
|
||||
DEMANGLE_NAMESPACE_BEGIN), and you can't introduce any code that
|
||||
depends on the libcxx dylib.
|
||||
|
||||
FIXME: Now that LLVM is a monorepo, it should be possible to
|
||||
de-duplicate this code, and have both LLVM and libcxxabi depend on a
|
||||
shared demangler library.
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
The tests are split up between libcxxabi/test/{unit,}test_demangle.cpp, and
|
||||
llvm/unittest/Demangle. The llvm directory should only get tests for stuff not
|
||||
included in the core library. In the future though, we should probably move all
|
||||
the tests to LLVM.
|
||||
|
||||
It is also a really good idea to run libFuzzer after non-trivial changes, see
|
||||
libcxxabi/fuzz/cxa_demangle_fuzzer.cpp and https://llvm.org/docs/LibFuzzer.html.
|
@ -1,5 +1,5 @@
|
||||
//===--- StringView.h -------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
//===--- StringView.h ----------------*- mode:c++;eval:(read-only-mode) -*-===//
|
||||
// Do not edit! See README.txt.
|
||||
// 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
|
||||
@ -7,14 +7,16 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// FIXME: Use std::string_view instead when we support C++17.
|
||||
// There are two copies of this file in the source tree. The one under
|
||||
// libcxxabi is the original and the one under llvm is the copy. Use
|
||||
// cp-to-llvm.sh to update the copy. See README.txt for more details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef DEMANGLE_STRINGVIEW_H
|
||||
#define DEMANGLE_STRINGVIEW_H
|
||||
#ifndef LLVM_DEMANGLE_STRINGVIEW_H
|
||||
#define LLVM_DEMANGLE_STRINGVIEW_H
|
||||
|
||||
#include "DemangleConfig.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
@ -36,29 +38,23 @@ public:
|
||||
StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {}
|
||||
StringView() : First(nullptr), Last(nullptr) {}
|
||||
|
||||
StringView substr(size_t From) const {
|
||||
return StringView(begin() + From, size() - From);
|
||||
StringView substr(size_t Pos, size_t Len = npos) const {
|
||||
assert(Pos <= size());
|
||||
if (Len > size() - Pos)
|
||||
Len = size() - Pos;
|
||||
return StringView(begin() + Pos, Len);
|
||||
}
|
||||
|
||||
size_t find(char C, size_t From = 0) const {
|
||||
size_t FindBegin = std::min(From, size());
|
||||
// Avoid calling memchr with nullptr.
|
||||
if (FindBegin < size()) {
|
||||
if (From < size()) {
|
||||
// Just forward to memchr, which is faster than a hand-rolled loop.
|
||||
if (const void *P = ::memchr(First + FindBegin, C, size() - FindBegin))
|
||||
if (const void *P = ::memchr(First + From, C, size() - From))
|
||||
return size_t(static_cast<const char *>(P) - First);
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
StringView substr(size_t From, size_t To) const {
|
||||
if (To >= size())
|
||||
To = size() - 1;
|
||||
if (From >= size())
|
||||
From = size() - 1;
|
||||
return StringView(First + From, First + To);
|
||||
}
|
||||
|
||||
StringView dropFront(size_t N = 1) const {
|
||||
if (N >= size())
|
||||
N = size();
|
||||
@ -105,7 +101,7 @@ public:
|
||||
bool startsWith(StringView Str) const {
|
||||
if (Str.size() > size())
|
||||
return false;
|
||||
return std::equal(Str.begin(), Str.end(), begin());
|
||||
return std::strncmp(Str.begin(), begin(), Str.size()) == 0;
|
||||
}
|
||||
|
||||
const char &operator[](size_t Idx) const { return *(begin() + Idx); }
|
||||
@ -118,7 +114,7 @@ public:
|
||||
|
||||
inline bool operator==(const StringView &LHS, const StringView &RHS) {
|
||||
return LHS.size() == RHS.size() &&
|
||||
std::equal(LHS.begin(), LHS.end(), RHS.begin());
|
||||
std::strncmp(LHS.begin(), RHS.begin(), LHS.size()) == 0;
|
||||
}
|
||||
|
||||
DEMANGLE_NAMESPACE_END
|
218
lib/external/llvm-demangle/include/llvm/Demangle/Utility.h
vendored
Normal file
218
lib/external/llvm-demangle/include/llvm/Demangle/Utility.h
vendored
Normal file
@ -0,0 +1,218 @@
|
||||
//===--- Utility.h -------------------*- mode:c++;eval:(read-only-mode) -*-===//
|
||||
// Do not edit! See README.txt.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Provide some utility classes for use in the demangler.
|
||||
// There are two copies of this file in the source tree. The one in libcxxabi
|
||||
// is the original and the one in llvm is the copy. Use cp-to-llvm.sh to update
|
||||
// the copy. See README.txt for more details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_DEMANGLE_UTILITY_H
|
||||
#define LLVM_DEMANGLE_UTILITY_H
|
||||
|
||||
#include "StringView.h"
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <limits>
|
||||
|
||||
DEMANGLE_NAMESPACE_BEGIN
|
||||
|
||||
// Stream that AST nodes write their string representation into after the AST
|
||||
// has been parsed.
|
||||
class OutputBuffer {
|
||||
char *Buffer = nullptr;
|
||||
size_t CurrentPosition = 0;
|
||||
size_t BufferCapacity = 0;
|
||||
|
||||
// Ensure there are at least N more positions in the buffer.
|
||||
void grow(size_t N) {
|
||||
size_t Need = N + CurrentPosition;
|
||||
if (Need > BufferCapacity) {
|
||||
// Reduce the number of reallocations, with a bit of hysteresis. The
|
||||
// number here is chosen so the first allocation will more-than-likely not
|
||||
// allocate more than 1K.
|
||||
Need += 1024 - 32;
|
||||
BufferCapacity *= 2;
|
||||
if (BufferCapacity < Need)
|
||||
BufferCapacity = Need;
|
||||
Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
|
||||
if (Buffer == nullptr)
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
|
||||
OutputBuffer &writeUnsigned(uint64_t N, bool isNeg = false) {
|
||||
std::array<char, 21> Temp;
|
||||
char *TempPtr = Temp.data() + Temp.size();
|
||||
|
||||
// Output at least one character.
|
||||
do {
|
||||
*--TempPtr = char('0' + N % 10);
|
||||
N /= 10;
|
||||
} while (N);
|
||||
|
||||
// Add negative sign.
|
||||
if (isNeg)
|
||||
*--TempPtr = '-';
|
||||
|
||||
return operator+=(StringView(TempPtr, Temp.data() + Temp.size()));
|
||||
}
|
||||
|
||||
public:
|
||||
OutputBuffer(char *StartBuf, size_t Size)
|
||||
: Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
|
||||
OutputBuffer() = default;
|
||||
// Non-copyable
|
||||
OutputBuffer(const OutputBuffer &) = delete;
|
||||
OutputBuffer &operator=(const OutputBuffer &) = delete;
|
||||
|
||||
operator StringView() const { return StringView(Buffer, CurrentPosition); }
|
||||
|
||||
void reset(char *Buffer_, size_t BufferCapacity_) {
|
||||
CurrentPosition = 0;
|
||||
Buffer = Buffer_;
|
||||
BufferCapacity = BufferCapacity_;
|
||||
}
|
||||
|
||||
/// If a ParameterPackExpansion (or similar type) is encountered, the offset
|
||||
/// into the pack that we're currently printing.
|
||||
unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
|
||||
unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
|
||||
|
||||
/// When zero, we're printing template args and '>' needs to be parenthesized.
|
||||
/// Use a counter so we can simply increment inside parentheses.
|
||||
unsigned GtIsGt = 1;
|
||||
|
||||
bool isGtInsideTemplateArgs() const { return GtIsGt == 0; }
|
||||
|
||||
void printOpen(char Open = '(') {
|
||||
GtIsGt++;
|
||||
*this += Open;
|
||||
}
|
||||
void printClose(char Close = ')') {
|
||||
GtIsGt--;
|
||||
*this += Close;
|
||||
}
|
||||
|
||||
OutputBuffer &operator+=(StringView R) {
|
||||
if (size_t Size = R.size()) {
|
||||
grow(Size);
|
||||
std::memcpy(Buffer + CurrentPosition, R.begin(), Size);
|
||||
CurrentPosition += Size;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
OutputBuffer &operator+=(char C) {
|
||||
grow(1);
|
||||
Buffer[CurrentPosition++] = C;
|
||||
return *this;
|
||||
}
|
||||
|
||||
OutputBuffer &prepend(StringView R) {
|
||||
size_t Size = R.size();
|
||||
|
||||
grow(Size);
|
||||
std::memmove(Buffer + Size, Buffer, CurrentPosition);
|
||||
std::memcpy(Buffer, R.begin(), Size);
|
||||
CurrentPosition += Size;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
OutputBuffer &operator<<(StringView R) { return (*this += R); }
|
||||
|
||||
OutputBuffer &operator<<(char C) { return (*this += C); }
|
||||
|
||||
OutputBuffer &operator<<(long long N) {
|
||||
return writeUnsigned(static_cast<unsigned long long>(std::abs(N)), N < 0);
|
||||
}
|
||||
|
||||
OutputBuffer &operator<<(unsigned long long N) {
|
||||
return writeUnsigned(N, false);
|
||||
}
|
||||
|
||||
OutputBuffer &operator<<(long N) {
|
||||
return this->operator<<(static_cast<long long>(N));
|
||||
}
|
||||
|
||||
OutputBuffer &operator<<(unsigned long N) {
|
||||
return this->operator<<(static_cast<unsigned long long>(N));
|
||||
}
|
||||
|
||||
OutputBuffer &operator<<(int N) {
|
||||
return this->operator<<(static_cast<long long>(N));
|
||||
}
|
||||
|
||||
OutputBuffer &operator<<(unsigned int N) {
|
||||
return this->operator<<(static_cast<unsigned long long>(N));
|
||||
}
|
||||
|
||||
void insert(size_t Pos, const char *S, size_t N) {
|
||||
assert(Pos <= CurrentPosition);
|
||||
if (N == 0)
|
||||
return;
|
||||
grow(N);
|
||||
std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos);
|
||||
std::memcpy(Buffer + Pos, S, N);
|
||||
CurrentPosition += N;
|
||||
}
|
||||
|
||||
size_t getCurrentPosition() const { return CurrentPosition; }
|
||||
void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
|
||||
|
||||
char back() const {
|
||||
assert(CurrentPosition);
|
||||
return Buffer[CurrentPosition - 1];
|
||||
}
|
||||
|
||||
bool empty() const { return CurrentPosition == 0; }
|
||||
|
||||
char *getBuffer() { return Buffer; }
|
||||
char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
|
||||
size_t getBufferCapacity() const { return BufferCapacity; }
|
||||
};
|
||||
|
||||
template <class T> class ScopedOverride {
|
||||
T &Loc;
|
||||
T Original;
|
||||
|
||||
public:
|
||||
ScopedOverride(T &Loc_) : ScopedOverride(Loc_, Loc_) {}
|
||||
|
||||
ScopedOverride(T &Loc_, T NewVal) : Loc(Loc_), Original(Loc_) {
|
||||
Loc_ = std::move(NewVal);
|
||||
}
|
||||
~ScopedOverride() { Loc = std::move(Original); }
|
||||
|
||||
ScopedOverride(const ScopedOverride &) = delete;
|
||||
ScopedOverride &operator=(const ScopedOverride &) = delete;
|
||||
};
|
||||
|
||||
inline bool initializeOutputBuffer(char *Buf, size_t *N, OutputBuffer &OB,
|
||||
size_t InitSize) {
|
||||
size_t BufferSize;
|
||||
if (Buf == nullptr) {
|
||||
Buf = static_cast<char *>(std::malloc(InitSize));
|
||||
if (Buf == nullptr)
|
||||
return false;
|
||||
BufferSize = InitSize;
|
||||
} else
|
||||
BufferSize = *N;
|
||||
|
||||
OB.reset(Buf, BufferSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
DEMANGLE_NAMESPACE_END
|
||||
|
||||
#endif
|
578
lib/external/llvm-demangle/source/DLangDemangle.cpp
vendored
Normal file
578
lib/external/llvm-demangle/source/DLangDemangle.cpp
vendored
Normal file
@ -0,0 +1,578 @@
|
||||
//===--- 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/StringView.h"
|
||||
#include "llvm/Demangle/Utility.h"
|
||||
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
|
||||
using namespace llvm;
|
||||
using llvm::itanium_demangle::OutputBuffer;
|
||||
using llvm::itanium_demangle::StringView;
|
||||
|
||||
namespace {
|
||||
|
||||
/// Demangle information structure.
|
||||
struct Demangler {
|
||||
/// Initialize the information structure we use to pass around information.
|
||||
///
|
||||
/// \param Mangled String to demangle.
|
||||
Demangler(const char *Mangled);
|
||||
|
||||
/// Extract and demangle the mangled symbol and append it to the output
|
||||
/// string.
|
||||
///
|
||||
/// \param Demangled Output buffer to write the demangled name.
|
||||
///
|
||||
/// \return The remaining string on success or nullptr on failure.
|
||||
///
|
||||
/// \see https://dlang.org/spec/abi.html#name_mangling .
|
||||
/// \see https://dlang.org/spec/abi.html#MangledName .
|
||||
const char *parseMangle(OutputBuffer *Demangled);
|
||||
|
||||
private:
|
||||
/// Extract and demangle a given mangled symbol and append it to the output
|
||||
/// string.
|
||||
///
|
||||
/// \param Demangled output buffer to write the demangled name.
|
||||
/// \param Mangled mangled symbol to be demangled.
|
||||
///
|
||||
/// \return The remaining string on success or nullptr on failure.
|
||||
///
|
||||
/// \see https://dlang.org/spec/abi.html#name_mangling .
|
||||
/// \see https://dlang.org/spec/abi.html#MangledName .
|
||||
const char *parseMangle(OutputBuffer *Demangled, const char *Mangled);
|
||||
|
||||
/// Extract the number from a given string.
|
||||
///
|
||||
/// \param Mangled string to extract the number.
|
||||
/// \param Ret assigned result value.
|
||||
///
|
||||
/// \return The remaining string on success or nullptr on failure.
|
||||
///
|
||||
/// \note A result larger than UINT_MAX is considered a failure.
|
||||
///
|
||||
/// \see https://dlang.org/spec/abi.html#Number .
|
||||
const char *decodeNumber(const char *Mangled, unsigned long &Ret);
|
||||
|
||||
/// Extract the back reference position from a given string.
|
||||
///
|
||||
/// \param Mangled string to extract the back reference position.
|
||||
/// \param Ret assigned result value.
|
||||
///
|
||||
/// \return the remaining string on success or nullptr on failure.
|
||||
///
|
||||
/// \note Ret is always >= 0 on success, and unspecified on failure
|
||||
///
|
||||
/// \see https://dlang.org/spec/abi.html#back_ref .
|
||||
/// \see https://dlang.org/spec/abi.html#NumberBackRef .
|
||||
const char *decodeBackrefPos(const char *Mangled, long &Ret);
|
||||
|
||||
/// Extract the symbol pointed by the back reference form a given string.
|
||||
///
|
||||
/// \param Mangled string to extract the back reference position.
|
||||
/// \param Ret assigned result value.
|
||||
///
|
||||
/// \return the remaining string on success or nullptr on failure.
|
||||
///
|
||||
/// \see https://dlang.org/spec/abi.html#back_ref .
|
||||
const char *decodeBackref(const char *Mangled, const char *&Ret);
|
||||
|
||||
/// Extract and demangle backreferenced symbol from a given mangled symbol
|
||||
/// and append it to the output string.
|
||||
///
|
||||
/// \param Demangled output buffer to write the demangled name.
|
||||
/// \param Mangled mangled symbol to be demangled.
|
||||
///
|
||||
/// \return the remaining string on success or nullptr on failure.
|
||||
///
|
||||
/// \see https://dlang.org/spec/abi.html#back_ref .
|
||||
/// \see https://dlang.org/spec/abi.html#IdentifierBackRef .
|
||||
const char *parseSymbolBackref(OutputBuffer *Demangled, const char *Mangled);
|
||||
|
||||
/// Extract and demangle backreferenced type from a given mangled symbol
|
||||
/// and append it to the output string.
|
||||
///
|
||||
/// \param Mangled mangled symbol to be demangled.
|
||||
///
|
||||
/// \return the remaining string on success or nullptr on failure.
|
||||
///
|
||||
/// \see https://dlang.org/spec/abi.html#back_ref .
|
||||
/// \see https://dlang.org/spec/abi.html#TypeBackRef .
|
||||
const char *parseTypeBackref(const char *Mangled);
|
||||
|
||||
/// Check whether it is the beginning of a symbol name.
|
||||
///
|
||||
/// \param Mangled string to extract the symbol name.
|
||||
///
|
||||
/// \return true on success, false otherwise.
|
||||
///
|
||||
/// \see https://dlang.org/spec/abi.html#SymbolName .
|
||||
bool isSymbolName(const char *Mangled);
|
||||
|
||||
/// Extract and demangle an identifier from a given mangled symbol append it
|
||||
/// to the output string.
|
||||
///
|
||||
/// \param Demangled Output buffer to write the demangled name.
|
||||
/// \param Mangled Mangled symbol to be demangled.
|
||||
///
|
||||
/// \return The remaining string on success or nullptr on failure.
|
||||
///
|
||||
/// \see https://dlang.org/spec/abi.html#SymbolName .
|
||||
const char *parseIdentifier(OutputBuffer *Demangled, const char *Mangled);
|
||||
|
||||
/// Extract and demangle the plain identifier from a given mangled symbol and
|
||||
/// prepend/append it to the output string, with a special treatment for some
|
||||
/// magic compiler generated symbols.
|
||||
///
|
||||
/// \param Demangled Output buffer to write the demangled name.
|
||||
/// \param Mangled Mangled symbol to be demangled.
|
||||
/// \param Len Length of the mangled symbol name.
|
||||
///
|
||||
/// \return The remaining string on success or nullptr on failure.
|
||||
///
|
||||
/// \see https://dlang.org/spec/abi.html#LName .
|
||||
const char *parseLName(OutputBuffer *Demangled, const char *Mangled,
|
||||
unsigned long Len);
|
||||
|
||||
/// Extract and demangle the qualified symbol from a given mangled symbol
|
||||
/// append it to the output string.
|
||||
///
|
||||
/// \param Demangled Output buffer to write the demangled name.
|
||||
/// \param Mangled Mangled symbol to be demangled.
|
||||
///
|
||||
/// \return The remaining string on success or nullptr on failure.
|
||||
///
|
||||
/// \see https://dlang.org/spec/abi.html#QualifiedName .
|
||||
const char *parseQualified(OutputBuffer *Demangled, const char *Mangled);
|
||||
|
||||
/// Extract and demangle a type from a given mangled symbol append it to
|
||||
/// the output string.
|
||||
///
|
||||
/// \param Mangled mangled symbol to be demangled.
|
||||
///
|
||||
/// \return the remaining string on success or nullptr on failure.
|
||||
///
|
||||
/// \see https://dlang.org/spec/abi.html#Type .
|
||||
const char *parseType(const char *Mangled);
|
||||
|
||||
/// The string we are demangling.
|
||||
const char *Str;
|
||||
/// The index of the last back reference.
|
||||
int LastBackref;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
const char *Demangler::decodeNumber(const char *Mangled, unsigned long &Ret) {
|
||||
// Return nullptr if trying to extract something that isn't a digit.
|
||||
if (Mangled == nullptr || !std::isdigit(*Mangled))
|
||||
return nullptr;
|
||||
|
||||
unsigned long Val = 0;
|
||||
|
||||
do {
|
||||
unsigned long Digit = Mangled[0] - '0';
|
||||
|
||||
// Check for overflow.
|
||||
if (Val > (std::numeric_limits<unsigned int>::max() - Digit) / 10)
|
||||
return nullptr;
|
||||
|
||||
Val = Val * 10 + Digit;
|
||||
++Mangled;
|
||||
} while (std::isdigit(*Mangled));
|
||||
|
||||
if (*Mangled == '\0')
|
||||
return nullptr;
|
||||
|
||||
Ret = Val;
|
||||
return Mangled;
|
||||
}
|
||||
|
||||
const char *Demangler::decodeBackrefPos(const char *Mangled, long &Ret) {
|
||||
// Return nullptr if trying to extract something that isn't a digit
|
||||
if (Mangled == nullptr || !std::isalpha(*Mangled))
|
||||
return nullptr;
|
||||
|
||||
// Any identifier or non-basic type that has been emitted to the mangled
|
||||
// symbol before will not be emitted again, but is referenced by a special
|
||||
// sequence encoding the relative position of the original occurrence in the
|
||||
// mangled symbol name.
|
||||
// Numbers in back references are encoded with base 26 by upper case letters
|
||||
// A-Z for higher digits but lower case letters a-z for the last digit.
|
||||
// NumberBackRef:
|
||||
// [a-z]
|
||||
// [A-Z] NumberBackRef
|
||||
// ^
|
||||
unsigned long Val = 0;
|
||||
|
||||
while (std::isalpha(*Mangled)) {
|
||||
// Check for overflow
|
||||
if (Val > (std::numeric_limits<unsigned long>::max() - 25) / 26)
|
||||
break;
|
||||
|
||||
Val *= 26;
|
||||
|
||||
if (Mangled[0] >= 'a' && Mangled[0] <= 'z') {
|
||||
Val += Mangled[0] - 'a';
|
||||
if ((long)Val <= 0)
|
||||
break;
|
||||
Ret = Val;
|
||||
return Mangled + 1;
|
||||
}
|
||||
|
||||
Val += Mangled[0] - 'A';
|
||||
++Mangled;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char *Demangler::decodeBackref(const char *Mangled, const char *&Ret) {
|
||||
assert(Mangled != nullptr && *Mangled == 'Q' && "Invalid back reference!");
|
||||
Ret = nullptr;
|
||||
|
||||
// Position of 'Q'
|
||||
const char *Qpos = Mangled;
|
||||
long RefPos;
|
||||
++Mangled;
|
||||
|
||||
Mangled = decodeBackrefPos(Mangled, RefPos);
|
||||
if (Mangled == nullptr)
|
||||
return nullptr;
|
||||
|
||||
if (RefPos > Qpos - Str)
|
||||
return nullptr;
|
||||
|
||||
// Set the position of the back reference.
|
||||
Ret = Qpos - RefPos;
|
||||
|
||||
return Mangled;
|
||||
}
|
||||
|
||||
const char *Demangler::parseSymbolBackref(OutputBuffer *Demangled,
|
||||
const char *Mangled) {
|
||||
// An identifier back reference always points to a digit 0 to 9.
|
||||
// IdentifierBackRef:
|
||||
// Q NumberBackRef
|
||||
// ^
|
||||
const char *Backref;
|
||||
unsigned long Len;
|
||||
|
||||
// Get position of the back reference
|
||||
Mangled = decodeBackref(Mangled, Backref);
|
||||
|
||||
// Must point to a simple identifier
|
||||
Backref = decodeNumber(Backref, Len);
|
||||
if (Backref == nullptr || strlen(Backref) < Len)
|
||||
return nullptr;
|
||||
|
||||
Backref = parseLName(Demangled, Backref, Len);
|
||||
if (Backref == nullptr)
|
||||
return nullptr;
|
||||
|
||||
return Mangled;
|
||||
}
|
||||
|
||||
const char *Demangler::parseTypeBackref(const char *Mangled) {
|
||||
// A type back reference always points to a letter.
|
||||
// TypeBackRef:
|
||||
// Q NumberBackRef
|
||||
// ^
|
||||
const char *Backref;
|
||||
|
||||
// If we appear to be moving backwards through the mangle string, then
|
||||
// bail as this may be a recursive back reference.
|
||||
if (Mangled - Str >= LastBackref)
|
||||
return nullptr;
|
||||
|
||||
int SaveRefPos = LastBackref;
|
||||
LastBackref = Mangled - Str;
|
||||
|
||||
// Get position of the back reference.
|
||||
Mangled = decodeBackref(Mangled, Backref);
|
||||
|
||||
// Can't decode back reference.
|
||||
if (Backref == nullptr)
|
||||
return nullptr;
|
||||
|
||||
// TODO: Add support for function type back references.
|
||||
Backref = parseType(Backref);
|
||||
|
||||
LastBackref = SaveRefPos;
|
||||
|
||||
if (Backref == nullptr)
|
||||
return nullptr;
|
||||
|
||||
return Mangled;
|
||||
}
|
||||
|
||||
bool Demangler::isSymbolName(const char *Mangled) {
|
||||
long Ret;
|
||||
const char *Qref = Mangled;
|
||||
|
||||
if (std::isdigit(*Mangled))
|
||||
return true;
|
||||
|
||||
// TODO: Handle template instances.
|
||||
|
||||
if (*Mangled != 'Q')
|
||||
return false;
|
||||
|
||||
Mangled = decodeBackrefPos(Mangled + 1, Ret);
|
||||
if (Mangled == nullptr || Ret > Qref - Str)
|
||||
return false;
|
||||
|
||||
return std::isdigit(Qref[-Ret]);
|
||||
}
|
||||
|
||||
const char *Demangler::parseMangle(OutputBuffer *Demangled,
|
||||
const char *Mangled) {
|
||||
// A D mangled symbol is comprised of both scope and type information.
|
||||
// MangleName:
|
||||
// _D QualifiedName Type
|
||||
// _D QualifiedName Z
|
||||
// ^
|
||||
// The caller should have guaranteed that the start pointer is at the
|
||||
// above location.
|
||||
// Note that type is never a function type, but only the return type of
|
||||
// a function or the type of a variable.
|
||||
Mangled += 2;
|
||||
|
||||
Mangled = parseQualified(Demangled, Mangled);
|
||||
|
||||
if (Mangled != nullptr) {
|
||||
// Artificial symbols end with 'Z' and have no type.
|
||||
if (*Mangled == 'Z')
|
||||
++Mangled;
|
||||
else {
|
||||
Mangled = parseType(Mangled);
|
||||
}
|
||||
}
|
||||
|
||||
return Mangled;
|
||||
}
|
||||
|
||||
const char *Demangler::parseQualified(OutputBuffer *Demangled,
|
||||
const char *Mangled) {
|
||||
// Qualified names are identifiers separated by their encoded length.
|
||||
// Nested functions also encode their argument types without specifying
|
||||
// what they return.
|
||||
// QualifiedName:
|
||||
// SymbolFunctionName
|
||||
// SymbolFunctionName QualifiedName
|
||||
// ^
|
||||
// SymbolFunctionName:
|
||||
// SymbolName
|
||||
// SymbolName TypeFunctionNoReturn
|
||||
// SymbolName M TypeFunctionNoReturn
|
||||
// SymbolName M TypeModifiers TypeFunctionNoReturn
|
||||
// The start pointer should be at the above location.
|
||||
|
||||
// Whether it has more than one symbol
|
||||
size_t NotFirst = false;
|
||||
do {
|
||||
// Skip over anonymous symbols.
|
||||
if (*Mangled == '0') {
|
||||
do
|
||||
++Mangled;
|
||||
while (*Mangled == '0');
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NotFirst)
|
||||
*Demangled << '.';
|
||||
NotFirst = true;
|
||||
|
||||
Mangled = parseIdentifier(Demangled, Mangled);
|
||||
|
||||
} while (Mangled && isSymbolName(Mangled));
|
||||
|
||||
return Mangled;
|
||||
}
|
||||
|
||||
const char *Demangler::parseIdentifier(OutputBuffer *Demangled,
|
||||
const char *Mangled) {
|
||||
unsigned long Len;
|
||||
|
||||
if (Mangled == nullptr || *Mangled == '\0')
|
||||
return nullptr;
|
||||
|
||||
if (*Mangled == 'Q')
|
||||
return parseSymbolBackref(Demangled, Mangled);
|
||||
|
||||
// TODO: Parse lengthless template instances.
|
||||
|
||||
const char *Endptr = decodeNumber(Mangled, Len);
|
||||
|
||||
if (Endptr == nullptr || Len == 0)
|
||||
return nullptr;
|
||||
|
||||
if (strlen(Endptr) < Len)
|
||||
return nullptr;
|
||||
|
||||
Mangled = Endptr;
|
||||
|
||||
// TODO: Parse template instances with a length prefix.
|
||||
|
||||
// There can be multiple different declarations in the same function that
|
||||
// have the same mangled name. To make the mangled names unique, a fake
|
||||
// parent in the form `__Sddd' is added to the symbol.
|
||||
if (Len >= 4 && Mangled[0] == '_' && Mangled[1] == '_' && Mangled[2] == 'S') {
|
||||
const char *NumPtr = Mangled + 3;
|
||||
while (NumPtr < (Mangled + Len) && std::isdigit(*NumPtr))
|
||||
++NumPtr;
|
||||
|
||||
if (Mangled + Len == NumPtr) {
|
||||
// Skip over the fake parent.
|
||||
Mangled += Len;
|
||||
return parseIdentifier(Demangled, Mangled);
|
||||
}
|
||||
|
||||
// Else demangle it as a plain identifier.
|
||||
}
|
||||
|
||||
return parseLName(Demangled, Mangled, Len);
|
||||
}
|
||||
|
||||
const char *Demangler::parseType(const char *Mangled) {
|
||||
if (*Mangled == '\0')
|
||||
return nullptr;
|
||||
|
||||
switch (*Mangled) {
|
||||
// TODO: Parse type qualifiers.
|
||||
// TODO: Parse function types.
|
||||
// TODO: Parse compound types.
|
||||
// TODO: Parse delegate types.
|
||||
// TODO: Parse tuple types.
|
||||
|
||||
// Basic types.
|
||||
case 'i':
|
||||
++Mangled;
|
||||
// TODO: Add type name dumping
|
||||
return Mangled;
|
||||
|
||||
// TODO: Add support for the rest of the basic types.
|
||||
|
||||
// Back referenced type.
|
||||
case 'Q':
|
||||
return parseTypeBackref(Mangled);
|
||||
|
||||
default: // unhandled.
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
const char *Demangler::parseLName(OutputBuffer *Demangled, const char *Mangled,
|
||||
unsigned long Len) {
|
||||
switch (Len) {
|
||||
case 6:
|
||||
if (strncmp(Mangled, "__initZ", Len + 1) == 0) {
|
||||
// The static initializer for a given symbol.
|
||||
Demangled->prepend("initializer for ");
|
||||
Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
|
||||
Mangled += Len;
|
||||
return Mangled;
|
||||
}
|
||||
if (strncmp(Mangled, "__vtblZ", Len + 1) == 0) {
|
||||
// The vtable symbol for a given class.
|
||||
Demangled->prepend("vtable for ");
|
||||
Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
|
||||
Mangled += Len;
|
||||
return Mangled;
|
||||
}
|
||||
break;
|
||||
|
||||
case 7:
|
||||
if (strncmp(Mangled, "__ClassZ", Len + 1) == 0) {
|
||||
// The classinfo symbol for a given class.
|
||||
Demangled->prepend("ClassInfo for ");
|
||||
Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
|
||||
Mangled += Len;
|
||||
return Mangled;
|
||||
}
|
||||
break;
|
||||
|
||||
case 11:
|
||||
if (strncmp(Mangled, "__InterfaceZ", Len + 1) == 0) {
|
||||
// The interface symbol for a given class.
|
||||
Demangled->prepend("Interface for ");
|
||||
Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
|
||||
Mangled += Len;
|
||||
return Mangled;
|
||||
}
|
||||
break;
|
||||
|
||||
case 12:
|
||||
if (strncmp(Mangled, "__ModuleInfoZ", Len + 1) == 0) {
|
||||
// The ModuleInfo symbol for a given module.
|
||||
Demangled->prepend("ModuleInfo for ");
|
||||
Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
|
||||
Mangled += Len;
|
||||
return Mangled;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
*Demangled << StringView(Mangled, Len);
|
||||
Mangled += Len;
|
||||
|
||||
return Mangled;
|
||||
}
|
||||
|
||||
Demangler::Demangler(const char *Mangled)
|
||||
: Str(Mangled), LastBackref(strlen(Mangled)) {}
|
||||
|
||||
const char *Demangler::parseMangle(OutputBuffer *Demangled) {
|
||||
return parseMangle(Demangled, this->Str);
|
||||
}
|
||||
|
||||
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";
|
||||
} else {
|
||||
|
||||
Demangler D = Demangler(MangledName);
|
||||
MangledName = D.parseMangle(&Demangled);
|
||||
|
||||
// Check that the entire symbol was successfully demangled.
|
||||
if (MangledName == nullptr || *MangledName != '\0') {
|
||||
std::free(Demangled.getBuffer());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
std::free(Demangled.getBuffer());
|
||||
return nullptr;
|
||||
}
|
64
lib/external/llvm-demangle/source/Demangle.cpp
vendored
Normal file
64
lib/external/llvm-demangle/source/Demangle.cpp
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
//===-- Demangle.cpp - Common demangling functions ------------------------===//
|
||||
//
|
||||
// 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 contains definitions of common demangling functions.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Demangle/Demangle.h"
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
static bool isItaniumEncoding(const char *S) {
|
||||
// Itanium encoding requires 1 or 3 leading underscores, followed by 'Z'.
|
||||
return std::strncmp(S, "_Z", 2) == 0 || std::strncmp(S, "___Z", 4) == 0;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
if (nonMicrosoftDemangle(S, Result))
|
||||
return Result;
|
||||
|
||||
if (S[0] == '_' && nonMicrosoftDemangle(S + 1, Result))
|
||||
return Result;
|
||||
|
||||
if (char *Demangled =
|
||||
microsoftDemangle(S, nullptr, nullptr, nullptr, nullptr)) {
|
||||
Result = Demangled;
|
||||
std::free(Demangled);
|
||||
return Result;
|
||||
}
|
||||
|
||||
return MangledName;
|
||||
}
|
||||
|
||||
bool llvm::nonMicrosoftDemangle(const char *MangledName, std::string &Result) {
|
||||
char *Demangled = nullptr;
|
||||
if (isItaniumEncoding(MangledName))
|
||||
Demangled = itaniumDemangle(MangledName, nullptr, nullptr, nullptr);
|
||||
else if (isRustEncoding(MangledName))
|
||||
Demangled = rustDemangle(MangledName);
|
||||
else if (isDLangEncoding(MangledName))
|
||||
Demangled = dlangDemangle(MangledName);
|
||||
|
||||
if (!Demangled)
|
||||
return false;
|
||||
|
||||
Result = Demangled;
|
||||
std::free(Demangled);
|
||||
return true;
|
||||
}
|
@ -19,9 +19,7 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::itanium_demangle;
|
||||
@ -174,6 +172,50 @@ struct DumpVisitor {
|
||||
return printStr("TemplateParamKind::Template");
|
||||
}
|
||||
}
|
||||
void print(Node::Prec P) {
|
||||
switch (P) {
|
||||
case Node::Prec::Primary:
|
||||
return printStr("Node::Prec::Primary");
|
||||
case Node::Prec::Postfix:
|
||||
return printStr("Node::Prec::Postfix");
|
||||
case Node::Prec::Unary:
|
||||
return printStr("Node::Prec::Unary");
|
||||
case Node::Prec::Cast:
|
||||
return printStr("Node::Prec::Cast");
|
||||
case Node::Prec::PtrMem:
|
||||
return printStr("Node::Prec::PtrMem");
|
||||
case Node::Prec::Multiplicative:
|
||||
return printStr("Node::Prec::Multiplicative");
|
||||
case Node::Prec::Additive:
|
||||
return printStr("Node::Prec::Additive");
|
||||
case Node::Prec::Shift:
|
||||
return printStr("Node::Prec::Shift");
|
||||
case Node::Prec::Spaceship:
|
||||
return printStr("Node::Prec::Spaceship");
|
||||
case Node::Prec::Relational:
|
||||
return printStr("Node::Prec::Relational");
|
||||
case Node::Prec::Equality:
|
||||
return printStr("Node::Prec::Equality");
|
||||
case Node::Prec::And:
|
||||
return printStr("Node::Prec::And");
|
||||
case Node::Prec::Xor:
|
||||
return printStr("Node::Prec::Xor");
|
||||
case Node::Prec::Ior:
|
||||
return printStr("Node::Prec::Ior");
|
||||
case Node::Prec::AndIf:
|
||||
return printStr("Node::Prec::AndIf");
|
||||
case Node::Prec::OrIf:
|
||||
return printStr("Node::Prec::OrIf");
|
||||
case Node::Prec::Conditional:
|
||||
return printStr("Node::Prec::Conditional");
|
||||
case Node::Prec::Assign:
|
||||
return printStr("Node::Prec::Assign");
|
||||
case Node::Prec::Comma:
|
||||
return printStr("Node::Prec::Comma");
|
||||
case Node::Prec::Default:
|
||||
return printStr("Node::Prec::Default");
|
||||
}
|
||||
}
|
||||
|
||||
void newLine() {
|
||||
printStr("\n");
|
||||
@ -333,21 +375,21 @@ char *llvm::itaniumDemangle(const char *MangledName, char *Buf,
|
||||
|
||||
int InternalStatus = demangle_success;
|
||||
Demangler Parser(MangledName, MangledName + std::strlen(MangledName));
|
||||
OutputStream S;
|
||||
OutputBuffer OB;
|
||||
|
||||
Node *AST = Parser.parse();
|
||||
|
||||
if (AST == nullptr)
|
||||
InternalStatus = demangle_invalid_mangled_name;
|
||||
else if (!initializeOutputStream(Buf, N, S, 1024))
|
||||
else if (!initializeOutputBuffer(Buf, N, OB, 1024))
|
||||
InternalStatus = demangle_memory_alloc_failure;
|
||||
else {
|
||||
assert(Parser.ForwardTemplateRefs.empty());
|
||||
AST->print(S);
|
||||
S += '\0';
|
||||
AST->print(OB);
|
||||
OB += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
Buf = S.getBuffer();
|
||||
*N = OB.getCurrentPosition();
|
||||
Buf = OB.getBuffer();
|
||||
}
|
||||
|
||||
if (Status)
|
||||
@ -385,14 +427,14 @@ bool ItaniumPartialDemangler::partialDemangle(const char *MangledName) {
|
||||
}
|
||||
|
||||
static char *printNode(const Node *RootNode, char *Buf, size_t *N) {
|
||||
OutputStream S;
|
||||
if (!initializeOutputStream(Buf, N, S, 128))
|
||||
OutputBuffer OB;
|
||||
if (!initializeOutputBuffer(Buf, N, OB, 128))
|
||||
return nullptr;
|
||||
RootNode->print(S);
|
||||
S += '\0';
|
||||
RootNode->print(OB);
|
||||
OB += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
return S.getBuffer();
|
||||
*N = OB.getCurrentPosition();
|
||||
return OB.getBuffer();
|
||||
}
|
||||
|
||||
char *ItaniumPartialDemangler::getFunctionBaseName(char *Buf, size_t *N) const {
|
||||
@ -406,8 +448,8 @@ char *ItaniumPartialDemangler::getFunctionBaseName(char *Buf, size_t *N) const {
|
||||
case Node::KAbiTagAttr:
|
||||
Name = static_cast<const AbiTagAttr *>(Name)->Base;
|
||||
continue;
|
||||
case Node::KStdQualifiedName:
|
||||
Name = static_cast<const StdQualifiedName *>(Name)->Child;
|
||||
case Node::KModuleEntity:
|
||||
Name = static_cast<const ModuleEntity *>(Name)->Name;
|
||||
continue;
|
||||
case Node::KNestedName:
|
||||
Name = static_cast<const NestedName *>(Name)->Name;
|
||||
@ -430,8 +472,8 @@ char *ItaniumPartialDemangler::getFunctionDeclContextName(char *Buf,
|
||||
return nullptr;
|
||||
const Node *Name = static_cast<const FunctionEncoding *>(RootNode)->getName();
|
||||
|
||||
OutputStream S;
|
||||
if (!initializeOutputStream(Buf, N, S, 128))
|
||||
OutputBuffer OB;
|
||||
if (!initializeOutputBuffer(Buf, N, OB, 128))
|
||||
return nullptr;
|
||||
|
||||
KeepGoingLocalFunction:
|
||||
@ -447,27 +489,27 @@ char *ItaniumPartialDemangler::getFunctionDeclContextName(char *Buf,
|
||||
break;
|
||||
}
|
||||
|
||||
if (Name->getKind() == Node::KModuleEntity)
|
||||
Name = static_cast<const ModuleEntity *>(Name)->Name;
|
||||
|
||||
switch (Name->getKind()) {
|
||||
case Node::KStdQualifiedName:
|
||||
S += "std";
|
||||
break;
|
||||
case Node::KNestedName:
|
||||
static_cast<const NestedName *>(Name)->Qual->print(S);
|
||||
static_cast<const NestedName *>(Name)->Qual->print(OB);
|
||||
break;
|
||||
case Node::KLocalName: {
|
||||
auto *LN = static_cast<const LocalName *>(Name);
|
||||
LN->Encoding->print(S);
|
||||
S += "::";
|
||||
LN->Encoding->print(OB);
|
||||
OB += "::";
|
||||
Name = LN->Entity;
|
||||
goto KeepGoingLocalFunction;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
S += '\0';
|
||||
OB += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
return S.getBuffer();
|
||||
*N = OB.getCurrentPosition();
|
||||
return OB.getBuffer();
|
||||
}
|
||||
|
||||
char *ItaniumPartialDemangler::getFunctionName(char *Buf, size_t *N) const {
|
||||
@ -483,17 +525,17 @@ char *ItaniumPartialDemangler::getFunctionParameters(char *Buf,
|
||||
return nullptr;
|
||||
NodeArray Params = static_cast<FunctionEncoding *>(RootNode)->getParams();
|
||||
|
||||
OutputStream S;
|
||||
if (!initializeOutputStream(Buf, N, S, 128))
|
||||
OutputBuffer OB;
|
||||
if (!initializeOutputBuffer(Buf, N, OB, 128))
|
||||
return nullptr;
|
||||
|
||||
S += '(';
|
||||
Params.printWithComma(S);
|
||||
S += ')';
|
||||
S += '\0';
|
||||
OB += '(';
|
||||
Params.printWithComma(OB);
|
||||
OB += ')';
|
||||
OB += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
return S.getBuffer();
|
||||
*N = OB.getCurrentPosition();
|
||||
return OB.getBuffer();
|
||||
}
|
||||
|
||||
char *ItaniumPartialDemangler::getFunctionReturnType(
|
||||
@ -501,18 +543,18 @@ char *ItaniumPartialDemangler::getFunctionReturnType(
|
||||
if (!isFunction())
|
||||
return nullptr;
|
||||
|
||||
OutputStream S;
|
||||
if (!initializeOutputStream(Buf, N, S, 128))
|
||||
OutputBuffer OB;
|
||||
if (!initializeOutputBuffer(Buf, N, OB, 128))
|
||||
return nullptr;
|
||||
|
||||
if (const Node *Ret =
|
||||
static_cast<const FunctionEncoding *>(RootNode)->getReturnType())
|
||||
Ret->print(S);
|
||||
Ret->print(OB);
|
||||
|
||||
S += '\0';
|
||||
OB += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
return S.getBuffer();
|
||||
*N = OB.getCurrentPosition();
|
||||
return OB.getBuffer();
|
||||
}
|
||||
|
||||
char *ItaniumPartialDemangler::finishDemangle(char *Buf, size_t *N) const {
|
||||
@ -552,8 +594,8 @@ bool ItaniumPartialDemangler::isCtorOrDtor() const {
|
||||
case Node::KNestedName:
|
||||
N = static_cast<const NestedName *>(N)->Name;
|
||||
break;
|
||||
case Node::KStdQualifiedName:
|
||||
N = static_cast<const StdQualifiedName *>(N)->Child;
|
||||
case Node::KModuleEntity:
|
||||
N = static_cast<const ModuleEntity *>(N)->Name;
|
||||
break;
|
||||
}
|
||||
}
|
@ -245,8 +245,8 @@ demanglePointerCVQualifiers(StringView &MangledName) {
|
||||
}
|
||||
|
||||
StringView Demangler::copyString(StringView Borrowed) {
|
||||
char *Stable = Arena.allocUnalignedBuffer(Borrowed.size() + 1);
|
||||
std::strcpy(Stable, Borrowed.begin());
|
||||
char *Stable = Arena.allocUnalignedBuffer(Borrowed.size());
|
||||
std::memcpy(Stable, Borrowed.begin(), Borrowed.size());
|
||||
|
||||
return {Stable, Borrowed.size()};
|
||||
}
|
||||
@ -823,11 +823,15 @@ SymbolNode *Demangler::parse(StringView &MangledName) {
|
||||
}
|
||||
|
||||
TagTypeNode *Demangler::parseTagUniqueName(StringView &MangledName) {
|
||||
if (!MangledName.consumeFront(".?A"))
|
||||
if (!MangledName.consumeFront(".?A")) {
|
||||
Error = true;
|
||||
return nullptr;
|
||||
}
|
||||
MangledName.consumeFront(".?A");
|
||||
if (MangledName.empty())
|
||||
if (MangledName.empty()) {
|
||||
Error = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return demangleClassType(MangledName);
|
||||
}
|
||||
@ -965,17 +969,14 @@ NamedIdentifierNode *Demangler::demangleBackRefName(StringView &MangledName) {
|
||||
void Demangler::memorizeIdentifier(IdentifierNode *Identifier) {
|
||||
// Render this class template name into a string buffer so that we can
|
||||
// memorize it for the purpose of back-referencing.
|
||||
OutputStream OS;
|
||||
if (!initializeOutputStream(nullptr, nullptr, OS, 1024))
|
||||
OutputBuffer OB;
|
||||
if (!initializeOutputBuffer(nullptr, nullptr, OB, 1024))
|
||||
// FIXME: Propagate out-of-memory as an error?
|
||||
std::terminate();
|
||||
Identifier->output(OS, OF_Default);
|
||||
OS << '\0';
|
||||
char *Name = OS.getBuffer();
|
||||
|
||||
StringView Owned = copyString(Name);
|
||||
Identifier->output(OB, OF_Default);
|
||||
StringView Owned = copyString(OB);
|
||||
memorizeString(Owned);
|
||||
std::free(Name);
|
||||
std::free(OB.getBuffer());
|
||||
}
|
||||
|
||||
IdentifierNode *
|
||||
@ -1107,7 +1108,7 @@ static void writeHexDigit(char *Buffer, uint8_t Digit) {
|
||||
*Buffer = (Digit < 10) ? ('0' + Digit) : ('A' + Digit - 10);
|
||||
}
|
||||
|
||||
static void outputHex(OutputStream &OS, unsigned C) {
|
||||
static void outputHex(OutputBuffer &OB, unsigned C) {
|
||||
assert (C != 0);
|
||||
|
||||
// It's easier to do the math if we can work from right to left, but we need
|
||||
@ -1130,43 +1131,43 @@ static void outputHex(OutputStream &OS, unsigned C) {
|
||||
TempBuffer[Pos--] = 'x';
|
||||
assert(Pos >= 0);
|
||||
TempBuffer[Pos--] = '\\';
|
||||
OS << StringView(&TempBuffer[Pos + 1]);
|
||||
OB << StringView(&TempBuffer[Pos + 1]);
|
||||
}
|
||||
|
||||
static void outputEscapedChar(OutputStream &OS, unsigned C) {
|
||||
static void outputEscapedChar(OutputBuffer &OB, unsigned C) {
|
||||
switch (C) {
|
||||
case '\0': // nul
|
||||
OS << "\\0";
|
||||
OB << "\\0";
|
||||
return;
|
||||
case '\'': // single quote
|
||||
OS << "\\\'";
|
||||
OB << "\\\'";
|
||||
return;
|
||||
case '\"': // double quote
|
||||
OS << "\\\"";
|
||||
OB << "\\\"";
|
||||
return;
|
||||
case '\\': // backslash
|
||||
OS << "\\\\";
|
||||
OB << "\\\\";
|
||||
return;
|
||||
case '\a': // bell
|
||||
OS << "\\a";
|
||||
OB << "\\a";
|
||||
return;
|
||||
case '\b': // backspace
|
||||
OS << "\\b";
|
||||
OB << "\\b";
|
||||
return;
|
||||
case '\f': // form feed
|
||||
OS << "\\f";
|
||||
OB << "\\f";
|
||||
return;
|
||||
case '\n': // new line
|
||||
OS << "\\n";
|
||||
OB << "\\n";
|
||||
return;
|
||||
case '\r': // carriage return
|
||||
OS << "\\r";
|
||||
OB << "\\r";
|
||||
return;
|
||||
case '\t': // tab
|
||||
OS << "\\t";
|
||||
OB << "\\t";
|
||||
return;
|
||||
case '\v': // vertical tab
|
||||
OS << "\\v";
|
||||
OB << "\\v";
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
@ -1174,11 +1175,11 @@ static void outputEscapedChar(OutputStream &OS, unsigned C) {
|
||||
|
||||
if (C > 0x1F && C < 0x7F) {
|
||||
// Standard ascii char.
|
||||
OS << (char)C;
|
||||
OB << (char)C;
|
||||
return;
|
||||
}
|
||||
|
||||
outputHex(OS, C);
|
||||
outputHex(OB, C);
|
||||
}
|
||||
|
||||
static unsigned countTrailingNullBytes(const uint8_t *StringBytes, int Length) {
|
||||
@ -1273,18 +1274,17 @@ FunctionSymbolNode *Demangler::demangleVcallThunkNode(StringView &MangledName) {
|
||||
EncodedStringLiteralNode *
|
||||
Demangler::demangleStringLiteral(StringView &MangledName) {
|
||||
// This function uses goto, so declare all variables up front.
|
||||
OutputStream OS;
|
||||
OutputBuffer OB;
|
||||
StringView CRC;
|
||||
uint64_t StringByteSize;
|
||||
bool IsWcharT = false;
|
||||
bool IsNegative = false;
|
||||
size_t CrcEndPos = 0;
|
||||
char *ResultBuffer = nullptr;
|
||||
|
||||
EncodedStringLiteralNode *Result = Arena.alloc<EncodedStringLiteralNode>();
|
||||
|
||||
// Must happen before the first `goto StringLiteralError`.
|
||||
if (!initializeOutputStream(nullptr, nullptr, OS, 1024))
|
||||
if (!initializeOutputBuffer(nullptr, nullptr, OB, 1024))
|
||||
// FIXME: Propagate out-of-memory as an error?
|
||||
std::terminate();
|
||||
|
||||
@ -1329,7 +1329,7 @@ Demangler::demangleStringLiteral(StringView &MangledName) {
|
||||
goto StringLiteralError;
|
||||
wchar_t W = demangleWcharLiteral(MangledName);
|
||||
if (StringByteSize != 2 || Result->IsTruncated)
|
||||
outputEscapedChar(OS, W);
|
||||
outputEscapedChar(OB, W);
|
||||
StringByteSize -= 2;
|
||||
if (Error)
|
||||
goto StringLiteralError;
|
||||
@ -1371,19 +1371,17 @@ Demangler::demangleStringLiteral(StringView &MangledName) {
|
||||
unsigned NextChar =
|
||||
decodeMultiByteChar(StringBytes, CharIndex, CharBytes);
|
||||
if (CharIndex + 1 < NumChars || Result->IsTruncated)
|
||||
outputEscapedChar(OS, NextChar);
|
||||
outputEscapedChar(OB, NextChar);
|
||||
}
|
||||
}
|
||||
|
||||
OS << '\0';
|
||||
ResultBuffer = OS.getBuffer();
|
||||
Result->DecodedString = copyString(ResultBuffer);
|
||||
std::free(ResultBuffer);
|
||||
Result->DecodedString = copyString(OB);
|
||||
std::free(OB.getBuffer());
|
||||
return Result;
|
||||
|
||||
StringLiteralError:
|
||||
Error = true;
|
||||
std::free(OS.getBuffer());
|
||||
std::free(OB.getBuffer());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1447,18 +1445,17 @@ Demangler::demangleLocallyScopedNamePiece(StringView &MangledName) {
|
||||
return nullptr;
|
||||
|
||||
// Render the parent symbol's name into a buffer.
|
||||
OutputStream OS;
|
||||
if (!initializeOutputStream(nullptr, nullptr, OS, 1024))
|
||||
OutputBuffer OB;
|
||||
if (!initializeOutputBuffer(nullptr, nullptr, OB, 1024))
|
||||
// FIXME: Propagate out-of-memory as an error?
|
||||
std::terminate();
|
||||
OS << '`';
|
||||
Scope->output(OS, OF_Default);
|
||||
OS << '\'';
|
||||
OS << "::`" << Number << "'";
|
||||
OS << '\0';
|
||||
char *Result = OS.getBuffer();
|
||||
Identifier->Name = copyString(Result);
|
||||
std::free(Result);
|
||||
OB << '`';
|
||||
Scope->output(OB, OF_Default);
|
||||
OB << '\'';
|
||||
OB << "::`" << Number << "'";
|
||||
|
||||
Identifier->Name = copyString(OB);
|
||||
std::free(OB.getBuffer());
|
||||
return Identifier;
|
||||
}
|
||||
|
||||
@ -1711,6 +1708,10 @@ CallingConv Demangler::demangleCallingConvention(StringView &MangledName) {
|
||||
return CallingConv::Eabi;
|
||||
case 'Q':
|
||||
return CallingConv::Vectorcall;
|
||||
case 'S':
|
||||
return CallingConv::Swift;
|
||||
case 'W':
|
||||
return CallingConv::SwiftAsync;
|
||||
}
|
||||
|
||||
return CallingConv::None;
|
||||
@ -2309,19 +2310,19 @@ void Demangler::dumpBackReferences() {
|
||||
(int)Backrefs.FunctionParamCount);
|
||||
|
||||
// Create an output stream so we can render each type.
|
||||
OutputStream OS;
|
||||
if (!initializeOutputStream(nullptr, nullptr, OS, 1024))
|
||||
OutputBuffer OB;
|
||||
if (!initializeOutputBuffer(nullptr, nullptr, OB, 1024))
|
||||
std::terminate();
|
||||
for (size_t I = 0; I < Backrefs.FunctionParamCount; ++I) {
|
||||
OS.setCurrentPosition(0);
|
||||
OB.setCurrentPosition(0);
|
||||
|
||||
TypeNode *T = Backrefs.FunctionParams[I];
|
||||
T->output(OS, OF_Default);
|
||||
T->output(OB, OF_Default);
|
||||
|
||||
std::printf(" [%d] - %.*s\n", (int)I, (int)OS.getCurrentPosition(),
|
||||
OS.getBuffer());
|
||||
StringView B = OB;
|
||||
std::printf(" [%d] - %.*s\n", (int)I, (int)B.size(), B.begin());
|
||||
}
|
||||
std::free(OS.getBuffer());
|
||||
std::free(OB.getBuffer());
|
||||
|
||||
if (Backrefs.FunctionParamCount > 0)
|
||||
std::printf("\n");
|
||||
@ -2338,7 +2339,7 @@ char *llvm::microsoftDemangle(const char *MangledName, size_t *NMangled,
|
||||
char *Buf, size_t *N,
|
||||
int *Status, MSDemangleFlags Flags) {
|
||||
Demangler D;
|
||||
OutputStream S;
|
||||
OutputBuffer OB;
|
||||
|
||||
StringView Name{MangledName};
|
||||
SymbolNode *AST = D.parse(Name);
|
||||
@ -2357,18 +2358,20 @@ char *llvm::microsoftDemangle(const char *MangledName, size_t *NMangled,
|
||||
OF = OutputFlags(OF | OF_NoReturnType);
|
||||
if (Flags & MSDF_NoMemberType)
|
||||
OF = OutputFlags(OF | OF_NoMemberType);
|
||||
if (Flags & MSDF_NoVariableType)
|
||||
OF = OutputFlags(OF | OF_NoVariableType);
|
||||
|
||||
int InternalStatus = demangle_success;
|
||||
if (D.Error)
|
||||
InternalStatus = demangle_invalid_mangled_name;
|
||||
else if (!initializeOutputStream(Buf, N, S, 1024))
|
||||
else if (!initializeOutputBuffer(Buf, N, OB, 1024))
|
||||
InternalStatus = demangle_memory_alloc_failure;
|
||||
else {
|
||||
AST->output(S, OF);
|
||||
S += '\0';
|
||||
AST->output(OB, OF);
|
||||
OB += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
Buf = S.getBuffer();
|
||||
*N = OB.getCurrentPosition();
|
||||
Buf = OB.getBuffer();
|
||||
}
|
||||
|
||||
if (Status)
|
@ -11,7 +11,6 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Demangle/MicrosoftDemangleNodes.h"
|
||||
#include "llvm/Demangle/DemangleConfig.h"
|
||||
#include "llvm/Demangle/Utility.h"
|
||||
#include <cctype>
|
||||
#include <string>
|
||||
@ -21,91 +20,97 @@ using namespace ms_demangle;
|
||||
|
||||
#define OUTPUT_ENUM_CLASS_VALUE(Enum, Value, Desc) \
|
||||
case Enum::Value: \
|
||||
OS << Desc; \
|
||||
OB << Desc; \
|
||||
break;
|
||||
|
||||
// Writes a space if the last token does not end with a punctuation.
|
||||
static void outputSpaceIfNecessary(OutputStream &OS) {
|
||||
if (OS.empty())
|
||||
static void outputSpaceIfNecessary(OutputBuffer &OB) {
|
||||
if (OB.empty())
|
||||
return;
|
||||
|
||||
char C = OS.back();
|
||||
char C = OB.back();
|
||||
if (std::isalnum(C) || C == '>')
|
||||
OS << " ";
|
||||
OB << " ";
|
||||
}
|
||||
|
||||
static void outputSingleQualifier(OutputStream &OS, Qualifiers Q) {
|
||||
static void outputSingleQualifier(OutputBuffer &OB, Qualifiers Q) {
|
||||
switch (Q) {
|
||||
case Q_Const:
|
||||
OS << "const";
|
||||
OB << "const";
|
||||
break;
|
||||
case Q_Volatile:
|
||||
OS << "volatile";
|
||||
OB << "volatile";
|
||||
break;
|
||||
case Q_Restrict:
|
||||
OS << "__restrict";
|
||||
OB << "__restrict";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool outputQualifierIfPresent(OutputStream &OS, Qualifiers Q,
|
||||
static bool outputQualifierIfPresent(OutputBuffer &OB, Qualifiers Q,
|
||||
Qualifiers Mask, bool NeedSpace) {
|
||||
if (!(Q & Mask))
|
||||
return NeedSpace;
|
||||
|
||||
if (NeedSpace)
|
||||
OS << " ";
|
||||
OB << " ";
|
||||
|
||||
outputSingleQualifier(OS, Mask);
|
||||
outputSingleQualifier(OB, Mask);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void outputQualifiers(OutputStream &OS, Qualifiers Q, bool SpaceBefore,
|
||||
static void outputQualifiers(OutputBuffer &OB, Qualifiers Q, bool SpaceBefore,
|
||||
bool SpaceAfter) {
|
||||
if (Q == Q_None)
|
||||
return;
|
||||
|
||||
size_t Pos1 = OS.getCurrentPosition();
|
||||
SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Const, SpaceBefore);
|
||||
SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Volatile, SpaceBefore);
|
||||
SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Restrict, SpaceBefore);
|
||||
size_t Pos2 = OS.getCurrentPosition();
|
||||
size_t Pos1 = OB.getCurrentPosition();
|
||||
SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Const, SpaceBefore);
|
||||
SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Volatile, SpaceBefore);
|
||||
SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Restrict, SpaceBefore);
|
||||
size_t Pos2 = OB.getCurrentPosition();
|
||||
if (SpaceAfter && Pos2 > Pos1)
|
||||
OS << " ";
|
||||
OB << " ";
|
||||
}
|
||||
|
||||
static void outputCallingConvention(OutputStream &OS, CallingConv CC) {
|
||||
outputSpaceIfNecessary(OS);
|
||||
static void outputCallingConvention(OutputBuffer &OB, CallingConv CC) {
|
||||
outputSpaceIfNecessary(OB);
|
||||
|
||||
switch (CC) {
|
||||
case CallingConv::Cdecl:
|
||||
OS << "__cdecl";
|
||||
OB << "__cdecl";
|
||||
break;
|
||||
case CallingConv::Fastcall:
|
||||
OS << "__fastcall";
|
||||
OB << "__fastcall";
|
||||
break;
|
||||
case CallingConv::Pascal:
|
||||
OS << "__pascal";
|
||||
OB << "__pascal";
|
||||
break;
|
||||
case CallingConv::Regcall:
|
||||
OS << "__regcall";
|
||||
OB << "__regcall";
|
||||
break;
|
||||
case CallingConv::Stdcall:
|
||||
OS << "__stdcall";
|
||||
OB << "__stdcall";
|
||||
break;
|
||||
case CallingConv::Thiscall:
|
||||
OS << "__thiscall";
|
||||
OB << "__thiscall";
|
||||
break;
|
||||
case CallingConv::Eabi:
|
||||
OS << "__eabi";
|
||||
OB << "__eabi";
|
||||
break;
|
||||
case CallingConv::Vectorcall:
|
||||
OS << "__vectorcall";
|
||||
OB << "__vectorcall";
|
||||
break;
|
||||
case CallingConv::Clrcall:
|
||||
OS << "__clrcall";
|
||||
OB << "__clrcall";
|
||||
break;
|
||||
case CallingConv::Swift:
|
||||
OB << "__attribute__((__swiftcall__)) ";
|
||||
break;
|
||||
case CallingConv::SwiftAsync:
|
||||
OB << "__attribute__((__swiftasynccall__)) ";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -113,14 +118,16 @@ static void outputCallingConvention(OutputStream &OS, CallingConv CC) {
|
||||
}
|
||||
|
||||
std::string Node::toString(OutputFlags Flags) const {
|
||||
OutputStream OS;
|
||||
initializeOutputStream(nullptr, nullptr, OS, 1024);
|
||||
this->output(OS, Flags);
|
||||
OS << '\0';
|
||||
return {OS.getBuffer()};
|
||||
OutputBuffer OB;
|
||||
initializeOutputBuffer(nullptr, nullptr, OB, 1024);
|
||||
this->output(OB, Flags);
|
||||
StringView SV = OB;
|
||||
std::string Owned(SV.begin(), SV.end());
|
||||
std::free(OB.getBuffer());
|
||||
return Owned;
|
||||
}
|
||||
|
||||
void PrimitiveTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
|
||||
void PrimitiveTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
|
||||
switch (PrimKind) {
|
||||
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Void, "void");
|
||||
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Bool, "bool");
|
||||
@ -144,107 +151,107 @@ void PrimitiveTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
|
||||
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ldouble, "long double");
|
||||
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Nullptr, "std::nullptr_t");
|
||||
}
|
||||
outputQualifiers(OS, Quals, true, false);
|
||||
outputQualifiers(OB, Quals, true, false);
|
||||
}
|
||||
|
||||
void NodeArrayNode::output(OutputStream &OS, OutputFlags Flags) const {
|
||||
output(OS, Flags, ", ");
|
||||
void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags) const {
|
||||
output(OB, Flags, ", ");
|
||||
}
|
||||
|
||||
void NodeArrayNode::output(OutputStream &OS, OutputFlags Flags,
|
||||
void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags,
|
||||
StringView Separator) const {
|
||||
if (Count == 0)
|
||||
return;
|
||||
if (Nodes[0])
|
||||
Nodes[0]->output(OS, Flags);
|
||||
Nodes[0]->output(OB, Flags);
|
||||
for (size_t I = 1; I < Count; ++I) {
|
||||
OS << Separator;
|
||||
Nodes[I]->output(OS, Flags);
|
||||
OB << Separator;
|
||||
Nodes[I]->output(OB, Flags);
|
||||
}
|
||||
}
|
||||
|
||||
void EncodedStringLiteralNode::output(OutputStream &OS,
|
||||
void EncodedStringLiteralNode::output(OutputBuffer &OB,
|
||||
OutputFlags Flags) const {
|
||||
switch (Char) {
|
||||
case CharKind::Wchar:
|
||||
OS << "L\"";
|
||||
OB << "L\"";
|
||||
break;
|
||||
case CharKind::Char:
|
||||
OS << "\"";
|
||||
OB << "\"";
|
||||
break;
|
||||
case CharKind::Char16:
|
||||
OS << "u\"";
|
||||
OB << "u\"";
|
||||
break;
|
||||
case CharKind::Char32:
|
||||
OS << "U\"";
|
||||
OB << "U\"";
|
||||
break;
|
||||
}
|
||||
OS << DecodedString << "\"";
|
||||
OB << DecodedString << "\"";
|
||||
if (IsTruncated)
|
||||
OS << "...";
|
||||
OB << "...";
|
||||
}
|
||||
|
||||
void IntegerLiteralNode::output(OutputStream &OS, OutputFlags Flags) const {
|
||||
void IntegerLiteralNode::output(OutputBuffer &OB, OutputFlags Flags) const {
|
||||
if (IsNegative)
|
||||
OS << '-';
|
||||
OS << Value;
|
||||
OB << '-';
|
||||
OB << Value;
|
||||
}
|
||||
|
||||
void TemplateParameterReferenceNode::output(OutputStream &OS,
|
||||
void TemplateParameterReferenceNode::output(OutputBuffer &OB,
|
||||
OutputFlags Flags) const {
|
||||
if (ThunkOffsetCount > 0)
|
||||
OS << "{";
|
||||
OB << "{";
|
||||
else if (Affinity == PointerAffinity::Pointer)
|
||||
OS << "&";
|
||||
OB << "&";
|
||||
|
||||
if (Symbol) {
|
||||
Symbol->output(OS, Flags);
|
||||
Symbol->output(OB, Flags);
|
||||
if (ThunkOffsetCount > 0)
|
||||
OS << ", ";
|
||||
OB << ", ";
|
||||
}
|
||||
|
||||
if (ThunkOffsetCount > 0)
|
||||
OS << ThunkOffsets[0];
|
||||
OB << ThunkOffsets[0];
|
||||
for (int I = 1; I < ThunkOffsetCount; ++I) {
|
||||
OS << ", " << ThunkOffsets[I];
|
||||
OB << ", " << ThunkOffsets[I];
|
||||
}
|
||||
if (ThunkOffsetCount > 0)
|
||||
OS << "}";
|
||||
OB << "}";
|
||||
}
|
||||
|
||||
void IdentifierNode::outputTemplateParameters(OutputStream &OS,
|
||||
void IdentifierNode::outputTemplateParameters(OutputBuffer &OB,
|
||||
OutputFlags Flags) const {
|
||||
if (!TemplateParams)
|
||||
return;
|
||||
OS << "<";
|
||||
TemplateParams->output(OS, Flags);
|
||||
OS << ">";
|
||||
OB << "<";
|
||||
TemplateParams->output(OB, Flags);
|
||||
OB << ">";
|
||||
}
|
||||
|
||||
void DynamicStructorIdentifierNode::output(OutputStream &OS,
|
||||
void DynamicStructorIdentifierNode::output(OutputBuffer &OB,
|
||||
OutputFlags Flags) const {
|
||||
if (IsDestructor)
|
||||
OS << "`dynamic atexit destructor for ";
|
||||
OB << "`dynamic atexit destructor for ";
|
||||
else
|
||||
OS << "`dynamic initializer for ";
|
||||
OB << "`dynamic initializer for ";
|
||||
|
||||
if (Variable) {
|
||||
OS << "`";
|
||||
Variable->output(OS, Flags);
|
||||
OS << "''";
|
||||
OB << "`";
|
||||
Variable->output(OB, Flags);
|
||||
OB << "''";
|
||||
} else {
|
||||
OS << "'";
|
||||
Name->output(OS, Flags);
|
||||
OS << "''";
|
||||
OB << "'";
|
||||
Name->output(OB, Flags);
|
||||
OB << "''";
|
||||
}
|
||||
}
|
||||
|
||||
void NamedIdentifierNode::output(OutputStream &OS, OutputFlags Flags) const {
|
||||
OS << Name;
|
||||
outputTemplateParameters(OS, Flags);
|
||||
void NamedIdentifierNode::output(OutputBuffer &OB, OutputFlags Flags) const {
|
||||
OB << Name;
|
||||
outputTemplateParameters(OB, Flags);
|
||||
}
|
||||
|
||||
void IntrinsicFunctionIdentifierNode::output(OutputStream &OS,
|
||||
void IntrinsicFunctionIdentifierNode::output(OutputBuffer &OB,
|
||||
OutputFlags Flags) const {
|
||||
switch (Operator) {
|
||||
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, New, "operator new");
|
||||
@ -342,188 +349,188 @@ void IntrinsicFunctionIdentifierNode::output(OutputStream &OS,
|
||||
case IntrinsicFunctionKind::None:
|
||||
break;
|
||||
}
|
||||
outputTemplateParameters(OS, Flags);
|
||||
outputTemplateParameters(OB, Flags);
|
||||
}
|
||||
|
||||
void LocalStaticGuardIdentifierNode::output(OutputStream &OS,
|
||||
void LocalStaticGuardIdentifierNode::output(OutputBuffer &OB,
|
||||
OutputFlags Flags) const {
|
||||
if (IsThread)
|
||||
OS << "`local static thread guard'";
|
||||
OB << "`local static thread guard'";
|
||||
else
|
||||
OS << "`local static guard'";
|
||||
OB << "`local static guard'";
|
||||
if (ScopeIndex > 0)
|
||||
OS << "{" << ScopeIndex << "}";
|
||||
OB << "{" << ScopeIndex << "}";
|
||||
}
|
||||
|
||||
void ConversionOperatorIdentifierNode::output(OutputStream &OS,
|
||||
void ConversionOperatorIdentifierNode::output(OutputBuffer &OB,
|
||||
OutputFlags Flags) const {
|
||||
OS << "operator";
|
||||
outputTemplateParameters(OS, Flags);
|
||||
OS << " ";
|
||||
TargetType->output(OS, Flags);
|
||||
OB << "operator";
|
||||
outputTemplateParameters(OB, Flags);
|
||||
OB << " ";
|
||||
TargetType->output(OB, Flags);
|
||||
}
|
||||
|
||||
void StructorIdentifierNode::output(OutputStream &OS, OutputFlags Flags) const {
|
||||
void StructorIdentifierNode::output(OutputBuffer &OB, OutputFlags Flags) const {
|
||||
if (IsDestructor)
|
||||
OS << "~";
|
||||
Class->output(OS, Flags);
|
||||
outputTemplateParameters(OS, Flags);
|
||||
OB << "~";
|
||||
Class->output(OB, Flags);
|
||||
outputTemplateParameters(OB, Flags);
|
||||
}
|
||||
|
||||
void LiteralOperatorIdentifierNode::output(OutputStream &OS,
|
||||
void LiteralOperatorIdentifierNode::output(OutputBuffer &OB,
|
||||
OutputFlags Flags) const {
|
||||
OS << "operator \"\"" << Name;
|
||||
outputTemplateParameters(OS, Flags);
|
||||
OB << "operator \"\"" << Name;
|
||||
outputTemplateParameters(OB, Flags);
|
||||
}
|
||||
|
||||
void FunctionSignatureNode::outputPre(OutputStream &OS,
|
||||
void FunctionSignatureNode::outputPre(OutputBuffer &OB,
|
||||
OutputFlags Flags) const {
|
||||
if (!(Flags & OF_NoAccessSpecifier)) {
|
||||
if (FunctionClass & FC_Public)
|
||||
OS << "public: ";
|
||||
OB << "public: ";
|
||||
if (FunctionClass & FC_Protected)
|
||||
OS << "protected: ";
|
||||
OB << "protected: ";
|
||||
if (FunctionClass & FC_Private)
|
||||
OS << "private: ";
|
||||
OB << "private: ";
|
||||
}
|
||||
|
||||
if (!(Flags & OF_NoMemberType)) {
|
||||
if (!(FunctionClass & FC_Global)) {
|
||||
if (FunctionClass & FC_Static)
|
||||
OS << "static ";
|
||||
OB << "static ";
|
||||
}
|
||||
if (FunctionClass & FC_Virtual)
|
||||
OS << "virtual ";
|
||||
OB << "virtual ";
|
||||
|
||||
if (FunctionClass & FC_ExternC)
|
||||
OS << "extern \"C\" ";
|
||||
OB << "extern \"C\" ";
|
||||
}
|
||||
|
||||
if (!(Flags & OF_NoReturnType) && ReturnType) {
|
||||
ReturnType->outputPre(OS, Flags);
|
||||
OS << " ";
|
||||
ReturnType->outputPre(OB, Flags);
|
||||
OB << " ";
|
||||
}
|
||||
|
||||
if (!(Flags & OF_NoCallingConvention))
|
||||
outputCallingConvention(OS, CallConvention);
|
||||
outputCallingConvention(OB, CallConvention);
|
||||
}
|
||||
|
||||
void FunctionSignatureNode::outputPost(OutputStream &OS,
|
||||
void FunctionSignatureNode::outputPost(OutputBuffer &OB,
|
||||
OutputFlags Flags) const {
|
||||
if (!(FunctionClass & FC_NoParameterList)) {
|
||||
OS << "(";
|
||||
OB << "(";
|
||||
if (Params)
|
||||
Params->output(OS, Flags);
|
||||
Params->output(OB, Flags);
|
||||
else
|
||||
OS << "void";
|
||||
OB << "void";
|
||||
|
||||
if (IsVariadic) {
|
||||
if (OS.back() != '(')
|
||||
OS << ", ";
|
||||
OS << "...";
|
||||
if (OB.back() != '(')
|
||||
OB << ", ";
|
||||
OB << "...";
|
||||
}
|
||||
OS << ")";
|
||||
OB << ")";
|
||||
}
|
||||
|
||||
if (Quals & Q_Const)
|
||||
OS << " const";
|
||||
OB << " const";
|
||||
if (Quals & Q_Volatile)
|
||||
OS << " volatile";
|
||||
OB << " volatile";
|
||||
if (Quals & Q_Restrict)
|
||||
OS << " __restrict";
|
||||
OB << " __restrict";
|
||||
if (Quals & Q_Unaligned)
|
||||
OS << " __unaligned";
|
||||
OB << " __unaligned";
|
||||
|
||||
if (IsNoexcept)
|
||||
OS << " noexcept";
|
||||
OB << " noexcept";
|
||||
|
||||
if (RefQualifier == FunctionRefQualifier::Reference)
|
||||
OS << " &";
|
||||
OB << " &";
|
||||
else if (RefQualifier == FunctionRefQualifier::RValueReference)
|
||||
OS << " &&";
|
||||
OB << " &&";
|
||||
|
||||
if (!(Flags & OF_NoReturnType) && ReturnType)
|
||||
ReturnType->outputPost(OS, Flags);
|
||||
ReturnType->outputPost(OB, Flags);
|
||||
}
|
||||
|
||||
void ThunkSignatureNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
|
||||
OS << "[thunk]: ";
|
||||
void ThunkSignatureNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
|
||||
OB << "[thunk]: ";
|
||||
|
||||
FunctionSignatureNode::outputPre(OS, Flags);
|
||||
FunctionSignatureNode::outputPre(OB, Flags);
|
||||
}
|
||||
|
||||
void ThunkSignatureNode::outputPost(OutputStream &OS, OutputFlags Flags) const {
|
||||
void ThunkSignatureNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {
|
||||
if (FunctionClass & FC_StaticThisAdjust) {
|
||||
OS << "`adjustor{" << ThisAdjust.StaticOffset << "}'";
|
||||
OB << "`adjustor{" << ThisAdjust.StaticOffset << "}'";
|
||||
} else if (FunctionClass & FC_VirtualThisAdjust) {
|
||||
if (FunctionClass & FC_VirtualThisAdjustEx) {
|
||||
OS << "`vtordispex{" << ThisAdjust.VBPtrOffset << ", "
|
||||
OB << "`vtordispex{" << ThisAdjust.VBPtrOffset << ", "
|
||||
<< ThisAdjust.VBOffsetOffset << ", " << ThisAdjust.VtordispOffset
|
||||
<< ", " << ThisAdjust.StaticOffset << "}'";
|
||||
} else {
|
||||
OS << "`vtordisp{" << ThisAdjust.VtordispOffset << ", "
|
||||
OB << "`vtordisp{" << ThisAdjust.VtordispOffset << ", "
|
||||
<< ThisAdjust.StaticOffset << "}'";
|
||||
}
|
||||
}
|
||||
|
||||
FunctionSignatureNode::outputPost(OS, Flags);
|
||||
FunctionSignatureNode::outputPost(OB, Flags);
|
||||
}
|
||||
|
||||
void PointerTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
|
||||
void PointerTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
|
||||
if (Pointee->kind() == NodeKind::FunctionSignature) {
|
||||
// If this is a pointer to a function, don't output the calling convention.
|
||||
// It needs to go inside the parentheses.
|
||||
const FunctionSignatureNode *Sig =
|
||||
static_cast<const FunctionSignatureNode *>(Pointee);
|
||||
Sig->outputPre(OS, OF_NoCallingConvention);
|
||||
Sig->outputPre(OB, OF_NoCallingConvention);
|
||||
} else
|
||||
Pointee->outputPre(OS, Flags);
|
||||
Pointee->outputPre(OB, Flags);
|
||||
|
||||
outputSpaceIfNecessary(OS);
|
||||
outputSpaceIfNecessary(OB);
|
||||
|
||||
if (Quals & Q_Unaligned)
|
||||
OS << "__unaligned ";
|
||||
OB << "__unaligned ";
|
||||
|
||||
if (Pointee->kind() == NodeKind::ArrayType) {
|
||||
OS << "(";
|
||||
OB << "(";
|
||||
} else if (Pointee->kind() == NodeKind::FunctionSignature) {
|
||||
OS << "(";
|
||||
OB << "(";
|
||||
const FunctionSignatureNode *Sig =
|
||||
static_cast<const FunctionSignatureNode *>(Pointee);
|
||||
outputCallingConvention(OS, Sig->CallConvention);
|
||||
OS << " ";
|
||||
outputCallingConvention(OB, Sig->CallConvention);
|
||||
OB << " ";
|
||||
}
|
||||
|
||||
if (ClassParent) {
|
||||
ClassParent->output(OS, Flags);
|
||||
OS << "::";
|
||||
ClassParent->output(OB, Flags);
|
||||
OB << "::";
|
||||
}
|
||||
|
||||
switch (Affinity) {
|
||||
case PointerAffinity::Pointer:
|
||||
OS << "*";
|
||||
OB << "*";
|
||||
break;
|
||||
case PointerAffinity::Reference:
|
||||
OS << "&";
|
||||
OB << "&";
|
||||
break;
|
||||
case PointerAffinity::RValueReference:
|
||||
OS << "&&";
|
||||
OB << "&&";
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
outputQualifiers(OS, Quals, false, false);
|
||||
outputQualifiers(OB, Quals, false, false);
|
||||
}
|
||||
|
||||
void PointerTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {
|
||||
void PointerTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {
|
||||
if (Pointee->kind() == NodeKind::ArrayType ||
|
||||
Pointee->kind() == NodeKind::FunctionSignature)
|
||||
OS << ")";
|
||||
OB << ")";
|
||||
|
||||
Pointee->outputPost(OS, Flags);
|
||||
Pointee->outputPost(OB, Flags);
|
||||
}
|
||||
|
||||
void TagTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
|
||||
void TagTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
|
||||
if (!(Flags & OF_NoTagSpecifier)) {
|
||||
switch (Tag) {
|
||||
OUTPUT_ENUM_CLASS_VALUE(TagKind, Class, "class");
|
||||
@ -531,59 +538,59 @@ void TagTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
|
||||
OUTPUT_ENUM_CLASS_VALUE(TagKind, Union, "union");
|
||||
OUTPUT_ENUM_CLASS_VALUE(TagKind, Enum, "enum");
|
||||
}
|
||||
OS << " ";
|
||||
OB << " ";
|
||||
}
|
||||
QualifiedName->output(OS, Flags);
|
||||
outputQualifiers(OS, Quals, true, false);
|
||||
QualifiedName->output(OB, Flags);
|
||||
outputQualifiers(OB, Quals, true, false);
|
||||
}
|
||||
|
||||
void TagTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {}
|
||||
void TagTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {}
|
||||
|
||||
void ArrayTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
|
||||
ElementType->outputPre(OS, Flags);
|
||||
outputQualifiers(OS, Quals, true, false);
|
||||
void ArrayTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
|
||||
ElementType->outputPre(OB, Flags);
|
||||
outputQualifiers(OB, Quals, true, false);
|
||||
}
|
||||
|
||||
void ArrayTypeNode::outputOneDimension(OutputStream &OS, OutputFlags Flags,
|
||||
void ArrayTypeNode::outputOneDimension(OutputBuffer &OB, OutputFlags Flags,
|
||||
Node *N) const {
|
||||
assert(N->kind() == NodeKind::IntegerLiteral);
|
||||
IntegerLiteralNode *ILN = static_cast<IntegerLiteralNode *>(N);
|
||||
if (ILN->Value != 0)
|
||||
ILN->output(OS, Flags);
|
||||
ILN->output(OB, Flags);
|
||||
}
|
||||
|
||||
void ArrayTypeNode::outputDimensionsImpl(OutputStream &OS,
|
||||
void ArrayTypeNode::outputDimensionsImpl(OutputBuffer &OB,
|
||||
OutputFlags Flags) const {
|
||||
if (Dimensions->Count == 0)
|
||||
return;
|
||||
|
||||
outputOneDimension(OS, Flags, Dimensions->Nodes[0]);
|
||||
outputOneDimension(OB, Flags, Dimensions->Nodes[0]);
|
||||
for (size_t I = 1; I < Dimensions->Count; ++I) {
|
||||
OS << "][";
|
||||
outputOneDimension(OS, Flags, Dimensions->Nodes[I]);
|
||||
OB << "][";
|
||||
outputOneDimension(OB, Flags, Dimensions->Nodes[I]);
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {
|
||||
OS << "[";
|
||||
outputDimensionsImpl(OS, Flags);
|
||||
OS << "]";
|
||||
void ArrayTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {
|
||||
OB << "[";
|
||||
outputDimensionsImpl(OB, Flags);
|
||||
OB << "]";
|
||||
|
||||
ElementType->outputPost(OS, Flags);
|
||||
ElementType->outputPost(OB, Flags);
|
||||
}
|
||||
|
||||
void SymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
|
||||
Name->output(OS, Flags);
|
||||
void SymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
|
||||
Name->output(OB, Flags);
|
||||
}
|
||||
|
||||
void FunctionSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
|
||||
Signature->outputPre(OS, Flags);
|
||||
outputSpaceIfNecessary(OS);
|
||||
Name->output(OS, Flags);
|
||||
Signature->outputPost(OS, Flags);
|
||||
void FunctionSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
|
||||
Signature->outputPre(OB, Flags);
|
||||
outputSpaceIfNecessary(OB);
|
||||
Name->output(OB, Flags);
|
||||
Signature->outputPost(OB, Flags);
|
||||
}
|
||||
|
||||
void VariableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
|
||||
void VariableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
|
||||
const char *AccessSpec = nullptr;
|
||||
bool IsStatic = true;
|
||||
switch (SC) {
|
||||
@ -601,53 +608,52 @@ void VariableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
|
||||
break;
|
||||
}
|
||||
if (!(Flags & OF_NoAccessSpecifier) && AccessSpec)
|
||||
OS << AccessSpec << ": ";
|
||||
OB << AccessSpec << ": ";
|
||||
if (!(Flags & OF_NoMemberType) && IsStatic)
|
||||
OS << "static ";
|
||||
OB << "static ";
|
||||
|
||||
if (Type) {
|
||||
Type->outputPre(OS, Flags);
|
||||
outputSpaceIfNecessary(OS);
|
||||
if (!(Flags & OF_NoVariableType) && Type) {
|
||||
Type->outputPre(OB, Flags);
|
||||
outputSpaceIfNecessary(OB);
|
||||
}
|
||||
Name->output(OS, Flags);
|
||||
if (Type)
|
||||
Type->outputPost(OS, Flags);
|
||||
Name->output(OB, Flags);
|
||||
if (!(Flags & OF_NoVariableType) && Type)
|
||||
Type->outputPost(OB, Flags);
|
||||
}
|
||||
|
||||
void CustomTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
|
||||
Identifier->output(OS, Flags);
|
||||
void CustomTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
|
||||
Identifier->output(OB, Flags);
|
||||
}
|
||||
void CustomTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {}
|
||||
void CustomTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {}
|
||||
|
||||
void QualifiedNameNode::output(OutputStream &OS, OutputFlags Flags) const {
|
||||
Components->output(OS, Flags, "::");
|
||||
void QualifiedNameNode::output(OutputBuffer &OB, OutputFlags Flags) const {
|
||||
Components->output(OB, Flags, "::");
|
||||
}
|
||||
|
||||
void RttiBaseClassDescriptorNode::output(OutputStream &OS,
|
||||
void RttiBaseClassDescriptorNode::output(OutputBuffer &OB,
|
||||
OutputFlags Flags) const {
|
||||
OS << "`RTTI Base Class Descriptor at (";
|
||||
OS << NVOffset << ", " << VBPtrOffset << ", " << VBTableOffset << ", "
|
||||
OB << "`RTTI Base Class Descriptor at (";
|
||||
OB << NVOffset << ", " << VBPtrOffset << ", " << VBTableOffset << ", "
|
||||
<< this->Flags;
|
||||
OS << ")'";
|
||||
OB << ")'";
|
||||
}
|
||||
|
||||
void LocalStaticGuardVariableNode::output(OutputStream &OS,
|
||||
void LocalStaticGuardVariableNode::output(OutputBuffer &OB,
|
||||
OutputFlags Flags) const {
|
||||
Name->output(OS, Flags);
|
||||
Name->output(OB, Flags);
|
||||
}
|
||||
|
||||
void VcallThunkIdentifierNode::output(OutputStream &OS,
|
||||
void VcallThunkIdentifierNode::output(OutputBuffer &OB,
|
||||
OutputFlags Flags) const {
|
||||
OS << "`vcall'{" << OffsetInVTable << ", {flat}}";
|
||||
OB << "`vcall'{" << OffsetInVTable << ", {flat}}";
|
||||
}
|
||||
|
||||
void SpecialTableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
|
||||
outputQualifiers(OS, Quals, false, true);
|
||||
Name->output(OS, Flags);
|
||||
void SpecialTableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
|
||||
outputQualifiers(OB, Quals, false, true);
|
||||
Name->output(OB, Flags);
|
||||
if (TargetName) {
|
||||
OS << "{for `";
|
||||
TargetName->output(OS, Flags);
|
||||
OS << "'}";
|
||||
OB << "{for `";
|
||||
TargetName->output(OB, Flags);
|
||||
OB << "'}";
|
||||
}
|
||||
return;
|
||||
}
|
1265
lib/external/llvm-demangle/source/RustDemangle.cpp
vendored
Normal file
1265
lib/external/llvm-demangle/source/RustDemangle.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
13
lib/external/llvm/CMakeLists.txt
vendored
13
lib/external/llvm/CMakeLists.txt
vendored
@ -1,13 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(LLVMDemangle)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
add_library(LLVMDemangle STATIC
|
||||
Demangle/Demangle.cpp
|
||||
Demangle/ItaniumDemangle.cpp
|
||||
Demangle/MicrosoftDemangle.cpp
|
||||
Demangle/MicrosoftDemangleNodes.cpp
|
||||
)
|
||||
|
||||
target_include_directories(LLVMDemangle PUBLIC include)
|
36
lib/external/llvm/Demangle/Demangle.cpp
vendored
36
lib/external/llvm/Demangle/Demangle.cpp
vendored
@ -1,36 +0,0 @@
|
||||
//===-- Demangle.cpp - Common demangling functions ------------------------===//
|
||||
//
|
||||
// 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 contains definitions of common demangling functions.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Demangle/Demangle.h"
|
||||
#include <cstdlib>
|
||||
|
||||
static bool isItaniumEncoding(const std::string &MangledName) {
|
||||
size_t Pos = MangledName.find_first_not_of('_');
|
||||
// A valid Itanium encoding requires 1-4 leading underscores, followed by 'Z'.
|
||||
return Pos > 0 && Pos <= 4 && MangledName[Pos] == 'Z';
|
||||
}
|
||||
|
||||
std::string llvm::demangle(const std::string &MangledName) {
|
||||
char *Demangled;
|
||||
if (isItaniumEncoding(MangledName))
|
||||
Demangled = itaniumDemangle(MangledName.c_str(), nullptr, nullptr, nullptr);
|
||||
else
|
||||
Demangled = microsoftDemangle(MangledName.c_str(), nullptr, nullptr,
|
||||
nullptr, nullptr);
|
||||
|
||||
if (!Demangled)
|
||||
return MangledName;
|
||||
|
||||
std::string Ret = Demangled;
|
||||
free(Demangled);
|
||||
return Ret;
|
||||
}
|
191
lib/external/llvm/include/llvm/Demangle/Utility.h
vendored
191
lib/external/llvm/include/llvm/Demangle/Utility.h
vendored
@ -1,191 +0,0 @@
|
||||
//===--- Utility.h ----------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Provide some utility classes for use in the demangler(s).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef DEMANGLE_UTILITY_H
|
||||
#define DEMANGLE_UTILITY_H
|
||||
|
||||
#include "StringView.h"
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
|
||||
DEMANGLE_NAMESPACE_BEGIN
|
||||
|
||||
// Stream that AST nodes write their string representation into after the AST
|
||||
// has been parsed.
|
||||
class OutputStream {
|
||||
char *Buffer = nullptr;
|
||||
size_t CurrentPosition = 0;
|
||||
size_t BufferCapacity = 0;
|
||||
|
||||
// Ensure there is at least n more positions in buffer.
|
||||
void grow(size_t N) {
|
||||
if (N + CurrentPosition >= BufferCapacity) {
|
||||
BufferCapacity *= 2;
|
||||
if (BufferCapacity < N + CurrentPosition)
|
||||
BufferCapacity = N + CurrentPosition;
|
||||
Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
|
||||
if (Buffer == nullptr)
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
|
||||
void writeUnsigned(uint64_t N, bool isNeg = false) {
|
||||
// Handle special case...
|
||||
if (N == 0) {
|
||||
*this << '0';
|
||||
return;
|
||||
}
|
||||
|
||||
char Temp[21];
|
||||
char *TempPtr = std::end(Temp);
|
||||
|
||||
while (N) {
|
||||
*--TempPtr = '0' + char(N % 10);
|
||||
N /= 10;
|
||||
}
|
||||
|
||||
// Add negative sign...
|
||||
if (isNeg)
|
||||
*--TempPtr = '-';
|
||||
this->operator<<(StringView(TempPtr, std::end(Temp)));
|
||||
}
|
||||
|
||||
public:
|
||||
OutputStream(char *StartBuf, size_t Size)
|
||||
: Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
|
||||
OutputStream() = default;
|
||||
void reset(char *Buffer_, size_t BufferCapacity_) {
|
||||
CurrentPosition = 0;
|
||||
Buffer = Buffer_;
|
||||
BufferCapacity = BufferCapacity_;
|
||||
}
|
||||
|
||||
/// If a ParameterPackExpansion (or similar type) is encountered, the offset
|
||||
/// into the pack that we're currently printing.
|
||||
unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
|
||||
unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
|
||||
|
||||
OutputStream &operator+=(StringView R) {
|
||||
size_t Size = R.size();
|
||||
if (Size == 0)
|
||||
return *this;
|
||||
grow(Size);
|
||||
std::memmove(Buffer + CurrentPosition, R.begin(), Size);
|
||||
CurrentPosition += Size;
|
||||
return *this;
|
||||
}
|
||||
|
||||
OutputStream &operator+=(char C) {
|
||||
grow(1);
|
||||
Buffer[CurrentPosition++] = C;
|
||||
return *this;
|
||||
}
|
||||
|
||||
OutputStream &operator<<(StringView R) { return (*this += R); }
|
||||
|
||||
OutputStream &operator<<(char C) { return (*this += C); }
|
||||
|
||||
OutputStream &operator<<(long long N) {
|
||||
if (N < 0)
|
||||
writeUnsigned(static_cast<unsigned long long>(-N), true);
|
||||
else
|
||||
writeUnsigned(static_cast<unsigned long long>(N));
|
||||
return *this;
|
||||
}
|
||||
|
||||
OutputStream &operator<<(unsigned long long N) {
|
||||
writeUnsigned(N, false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
OutputStream &operator<<(long N) {
|
||||
return this->operator<<(static_cast<long long>(N));
|
||||
}
|
||||
|
||||
OutputStream &operator<<(unsigned long N) {
|
||||
return this->operator<<(static_cast<unsigned long long>(N));
|
||||
}
|
||||
|
||||
OutputStream &operator<<(int N) {
|
||||
return this->operator<<(static_cast<long long>(N));
|
||||
}
|
||||
|
||||
OutputStream &operator<<(unsigned int N) {
|
||||
return this->operator<<(static_cast<unsigned long long>(N));
|
||||
}
|
||||
|
||||
size_t getCurrentPosition() const { return CurrentPosition; }
|
||||
void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
|
||||
|
||||
char back() const {
|
||||
return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
|
||||
}
|
||||
|
||||
bool empty() const { return CurrentPosition == 0; }
|
||||
|
||||
char *getBuffer() { return Buffer; }
|
||||
char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
|
||||
size_t getBufferCapacity() const { return BufferCapacity; }
|
||||
};
|
||||
|
||||
template <class T> class SwapAndRestore {
|
||||
T &Restore;
|
||||
T OriginalValue;
|
||||
bool ShouldRestore = true;
|
||||
|
||||
public:
|
||||
SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {}
|
||||
|
||||
SwapAndRestore(T &Restore_, T NewVal)
|
||||
: Restore(Restore_), OriginalValue(Restore) {
|
||||
Restore = std::move(NewVal);
|
||||
}
|
||||
~SwapAndRestore() {
|
||||
if (ShouldRestore)
|
||||
Restore = std::move(OriginalValue);
|
||||
}
|
||||
|
||||
void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; }
|
||||
|
||||
void restoreNow(bool Force) {
|
||||
if (!Force && !ShouldRestore)
|
||||
return;
|
||||
|
||||
Restore = std::move(OriginalValue);
|
||||
ShouldRestore = false;
|
||||
}
|
||||
|
||||
SwapAndRestore(const SwapAndRestore &) = delete;
|
||||
SwapAndRestore &operator=(const SwapAndRestore &) = delete;
|
||||
};
|
||||
|
||||
inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S,
|
||||
size_t InitSize) {
|
||||
size_t BufferSize;
|
||||
if (Buf == nullptr) {
|
||||
Buf = static_cast<char *>(std::malloc(InitSize));
|
||||
if (Buf == nullptr)
|
||||
return false;
|
||||
BufferSize = InitSize;
|
||||
} else
|
||||
BufferSize = *N;
|
||||
|
||||
S.reset(Buf, BufferSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
DEMANGLE_NAMESPACE_END
|
||||
|
||||
#endif
|
@ -53,8 +53,8 @@ else()
|
||||
endif()
|
||||
|
||||
if (NOT USE_SYSTEM_LLVM)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../external/llvm ${CMAKE_CURRENT_BINARY_DIR}/external/llvm EXCLUDE_FROM_ALL)
|
||||
set_target_properties(LLVMDemangle PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../external/llvm-demangle ${CMAKE_CURRENT_BINARY_DIR}/external/llvm-demangle EXCLUDE_FROM_ALL)
|
||||
set_target_properties(llvm-demangle PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
else()
|
||||
find_package(LLVM REQUIRED Demangle)
|
||||
endif()
|
||||
@ -163,4 +163,4 @@ if (APPLE)
|
||||
target_link_libraries(libimhex PUBLIC ${FOUNDATION})
|
||||
endif ()
|
||||
|
||||
target_link_libraries(libimhex PUBLIC dl imgui nfd magic ${CAPSTONE_LIBRARIES} LLVMDemangle microtar ${NLOHMANN_JSON_LIBRARIES} ${YARA_LIBRARIES} ${LIBCURL_LIBRARIES} ${MBEDTLS_LIBRARIES} ${FMT_LIBRARIES} ${Python_LIBRARIES} libromfs libpl)
|
||||
target_link_libraries(libimhex PUBLIC dl imgui nfd magic ${CAPSTONE_LIBRARIES} llvm-demangle microtar ${NLOHMANN_JSON_LIBRARIES} ${YARA_LIBRARIES} ${LIBCURL_LIBRARIES} ${MBEDTLS_LIBRARIES} ${FMT_LIBRARIES} ${Python_LIBRARIES} libromfs libpl)
|
||||
|
@ -67,7 +67,7 @@ add_library(${PROJECT_NAME} SHARED
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE include)
|
||||
|
||||
# Add additional libraries here #
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE libimhex LLVMDemangle)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE libimhex llvm-demangle)
|
||||
|
||||
# ---- No need to change anything from here downwards unless you know what you're doing ---- #
|
||||
|
||||
|
@ -37,15 +37,21 @@ namespace hex::plugin::builtin {
|
||||
using namespace hex::literals;
|
||||
|
||||
void drawDemangler() {
|
||||
static std::vector<char> mangledBuffer(0xF'FFFF, 0x00);
|
||||
static std::string demangledName;
|
||||
static std::string mangledName, demangledName;
|
||||
|
||||
if (ImGui::InputText("hex.builtin.tools.demangler.mangled"_lang, mangledBuffer.data(), 0xF'FFFF)) {
|
||||
demangledName = llvm::demangle(mangledBuffer.data());
|
||||
if (ImGui::InputTextWithHint("hex.builtin.tools.demangler.mangled"_lang, "Itanium, MSVC, Dlang & Rust", mangledName)) {
|
||||
demangledName = llvm::demangle(mangledName);
|
||||
|
||||
if (demangledName == mangledName) {
|
||||
demangledName = "???";
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::InputText("hex.builtin.tools.demangler.demangled"_lang, demangledName.data(), demangledName.size(), ImGuiInputTextFlags_ReadOnly);
|
||||
ImGui::NewLine();
|
||||
ImGui::Header("hex.builtin.tools.demangler.demangled"_lang);
|
||||
if (ImGui::BeginChild("demangled", ImVec2(0, 200_scaled), true)) {
|
||||
ImGui::TextFormattedWrapped("{}", demangledName);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
void drawASCIITable() {
|
||||
|
@ -594,7 +594,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.nodes.visualizer.byte_distribution.header", "Byteverteilung" },
|
||||
|
||||
|
||||
{ "hex.builtin.tools.demangler", "Itanium/MSVC demangler" },
|
||||
{ "hex.builtin.tools.demangler", "LLVM Demangler" },
|
||||
{ "hex.builtin.tools.demangler.mangled", "Mangled Namen" },
|
||||
{ "hex.builtin.tools.demangler.demangled", "Demangled Namen" },
|
||||
{ "hex.builtin.tools.ascii_table", "ASCII Tabelle" },
|
||||
|
@ -598,7 +598,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.nodes.visualizer.byte_distribution.header", "Byte Distribution" },
|
||||
|
||||
|
||||
{ "hex.builtin.tools.demangler", "Itanium/MSVC demangler" },
|
||||
{ "hex.builtin.tools.demangler", "LLVM Demangler" },
|
||||
{ "hex.builtin.tools.demangler.mangled", "Mangled name" },
|
||||
{ "hex.builtin.tools.demangler.demangled", "Demangled name" },
|
||||
{ "hex.builtin.tools.ascii_table", "ASCII table" },
|
||||
|
@ -602,7 +602,7 @@ namespace hex::plugin::builtin {
|
||||
//{ "hex.builtin.nodes.visualizer.byte_distribution.header", "Byte Distribution" },
|
||||
|
||||
|
||||
{ "hex.builtin.tools.demangler", "Itanium/MSVC demangler" },
|
||||
{ "hex.builtin.tools.demangler", "LLVM Demangler" },
|
||||
{ "hex.builtin.tools.demangler.mangled", "Nome Mangled" },
|
||||
{ "hex.builtin.tools.demangler.demangled", "Nome Demangled" },
|
||||
{ "hex.builtin.tools.ascii_table", "Tavola ASCII" },
|
||||
|
@ -599,7 +599,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.nodes.visualizer.byte_distribution.header", "バイト分布" },
|
||||
|
||||
|
||||
{ "hex.builtin.tools.demangler", "Itanium/MSVCデマングラー" },
|
||||
{ "hex.builtin.tools.demangler", "LLVMデマングラー" },
|
||||
{ "hex.builtin.tools.demangler.mangled", "マングリング名" },
|
||||
{ "hex.builtin.tools.demangler.demangled", "デマングリング名" },
|
||||
{ "hex.builtin.tools.ascii_table", "ASCIIテーブル" },
|
||||
|
@ -594,7 +594,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.nodes.visualizer.byte_distribution.header", "Byte Distribution" },
|
||||
|
||||
|
||||
{ "hex.builtin.tools.demangler", "Itanium/MSVC demangler" },
|
||||
{ "hex.builtin.tools.demangler", "LLVM Demangler" },
|
||||
{ "hex.builtin.tools.demangler.mangled", "Mangled name" },
|
||||
{ "hex.builtin.tools.demangler.demangled", "Demangled name" },
|
||||
{ "hex.builtin.tools.ascii_table", "ASCII table" },
|
||||
|
@ -599,7 +599,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.nodes.visualizer.byte_distribution.header", "字节分布" },
|
||||
|
||||
|
||||
{ "hex.builtin.tools.demangler", "Itanium/MSVC 名还原" },
|
||||
{ "hex.builtin.tools.demangler", "LLVM 名还原" },
|
||||
{ "hex.builtin.tools.demangler.mangled", "修饰名" },
|
||||
{ "hex.builtin.tools.demangler.demangled", "还原名" },
|
||||
{ "hex.builtin.tools.ascii_table", "ASCII 表" },
|
||||
|
@ -595,7 +595,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.nodes.visualizer.byte_distribution.header", "Byte Distribution" },
|
||||
|
||||
|
||||
{ "hex.builtin.tools.demangler", "Itanium/MSVC demangler" },
|
||||
{ "hex.builtin.tools.demangler", "LLVM Demangler" },
|
||||
{ "hex.builtin.tools.demangler.mangled", "Mangled name" },
|
||||
{ "hex.builtin.tools.demangler.demangled", "Demangled name" },
|
||||
{ "hex.builtin.tools.ascii_table", "ASCII 表" },
|
||||
|
Loading…
x
Reference in New Issue
Block a user