mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-26 03:15:19 +00:00
Reland "[DebugInfo][CodeView] Use <lambda_n> as the display name for lambdas"
with fix to test case and stringrefs. Currently (for codeview) lambdas have a string like `<lambda_0>` in their mangled name, and don't have any display name. This change uses the `<lambda_0>` as the display name, which helps distinguish between lambdas in -gline-tables-only, since there are no linkage names there. It also changes how we display lambda names; previously we used `<unnamed-tag>`; now it will show `<lambda_0>`. I added a function to the mangling context code to create this string; for Itanium it just returns an empty string. Bug: https://bugs.llvm.org/show_bug.cgi?id=48432 Reviewed By: rnk Differential Revision: https://reviews.llvm.org/D95187 This reverts 9b21d4b9434d2d4796b0d60d64f6ded9bac95441
This commit is contained in:
parent
edecee3826
commit
d5f5deee9e
@ -89,6 +89,17 @@ public:
|
||||
return Result.first->second;
|
||||
}
|
||||
|
||||
uint64_t getAnonymousStructIdForDebugInfo(const NamedDecl *D) {
|
||||
llvm::DenseMap<const NamedDecl *, uint64_t>::iterator Result =
|
||||
AnonStructIds.find(D);
|
||||
// The decl should already be inserted, but return 0 in case it is not.
|
||||
if (Result == AnonStructIds.end())
|
||||
return 0;
|
||||
return Result->second;
|
||||
}
|
||||
|
||||
virtual std::string getLambdaString(const CXXRecordDecl *Lambda) = 0;
|
||||
|
||||
/// @name Mangler Entry Points
|
||||
/// @{
|
||||
|
||||
|
@ -203,6 +203,36 @@ public:
|
||||
disc = discriminator-2;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string getLambdaString(const CXXRecordDecl *Lambda) override {
|
||||
// This function matches the one in MicrosoftMangle, which returns
|
||||
// the string that is used in lambda mangled names.
|
||||
assert(Lambda->isLambda() && "RD must be a lambda!");
|
||||
std::string Name("<lambda");
|
||||
Decl *LambdaContextDecl = Lambda->getLambdaContextDecl();
|
||||
unsigned LambdaManglingNumber = Lambda->getLambdaManglingNumber();
|
||||
unsigned LambdaId;
|
||||
const ParmVarDecl *Parm = dyn_cast_or_null<ParmVarDecl>(LambdaContextDecl);
|
||||
const FunctionDecl *Func =
|
||||
Parm ? dyn_cast<FunctionDecl>(Parm->getDeclContext()) : nullptr;
|
||||
|
||||
if (Func) {
|
||||
unsigned DefaultArgNo =
|
||||
Func->getNumParams() - Parm->getFunctionScopeIndex();
|
||||
Name += llvm::utostr(DefaultArgNo);
|
||||
Name += "_";
|
||||
}
|
||||
|
||||
if (LambdaManglingNumber)
|
||||
LambdaId = LambdaManglingNumber;
|
||||
else
|
||||
LambdaId = getAnonymousStructIdForDebugInfo(Lambda);
|
||||
|
||||
Name += llvm::utostr(LambdaId);
|
||||
Name += '>';
|
||||
return Name;
|
||||
}
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
|
@ -228,6 +228,34 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string getLambdaString(const CXXRecordDecl *Lambda) override {
|
||||
assert(Lambda->isLambda() && "RD must be a lambda!");
|
||||
std::string Name("<lambda_");
|
||||
|
||||
Decl *LambdaContextDecl = Lambda->getLambdaContextDecl();
|
||||
unsigned LambdaManglingNumber = Lambda->getLambdaManglingNumber();
|
||||
unsigned LambdaId;
|
||||
const ParmVarDecl *Parm = dyn_cast_or_null<ParmVarDecl>(LambdaContextDecl);
|
||||
const FunctionDecl *Func =
|
||||
Parm ? dyn_cast<FunctionDecl>(Parm->getDeclContext()) : nullptr;
|
||||
|
||||
if (Func) {
|
||||
unsigned DefaultArgNo =
|
||||
Func->getNumParams() - Parm->getFunctionScopeIndex();
|
||||
Name += llvm::utostr(DefaultArgNo);
|
||||
Name += "_";
|
||||
}
|
||||
|
||||
if (LambdaManglingNumber)
|
||||
LambdaId = LambdaManglingNumber;
|
||||
else
|
||||
LambdaId = getLambdaIdForDebugInfo(Lambda);
|
||||
|
||||
Name += llvm::utostr(LambdaId);
|
||||
Name += ">";
|
||||
return Name;
|
||||
}
|
||||
|
||||
unsigned getLambdaId(const CXXRecordDecl *RD) {
|
||||
assert(RD->isLambda() && "RD must be a lambda!");
|
||||
assert(!RD->isExternallyVisible() && "RD must not be visible!");
|
||||
@ -238,6 +266,19 @@ public:
|
||||
return Result.first->second;
|
||||
}
|
||||
|
||||
unsigned getLambdaIdForDebugInfo(const CXXRecordDecl *RD) {
|
||||
assert(RD->isLambda() && "RD must be a lambda!");
|
||||
assert(!RD->isExternallyVisible() && "RD must not be visible!");
|
||||
assert(RD->getLambdaManglingNumber() == 0 &&
|
||||
"RD must not have a mangling number!");
|
||||
llvm::DenseMap<const CXXRecordDecl *, unsigned>::iterator Result =
|
||||
LambdaIds.find(RD);
|
||||
// The lambda should exist, but return 0 in case it doesn't.
|
||||
if (Result == LambdaIds.end())
|
||||
return 0;
|
||||
return Result->second;
|
||||
}
|
||||
|
||||
/// Return a character sequence that is (somewhat) unique to the TU suitable
|
||||
/// for mangling anonymous namespaces.
|
||||
StringRef getAnonymousNamespaceHash() const {
|
||||
|
@ -317,8 +317,9 @@ StringRef CGDebugInfo::getClassName(const RecordDecl *RD) {
|
||||
if (const IdentifierInfo *II = RD->getIdentifier())
|
||||
return II->getName();
|
||||
|
||||
// The CodeView printer in LLVM wants to see the names of unnamed types: it is
|
||||
// used to reconstruct the fully qualified type names.
|
||||
// The CodeView printer in LLVM wants to see the names of unnamed types
|
||||
// because they need to have a unique identifier.
|
||||
// These names are used to reconstruct the fully qualified type names.
|
||||
if (CGM.getCodeGenOpts().EmitCodeView) {
|
||||
if (const TypedefNameDecl *D = RD->getTypedefNameForAnonDecl()) {
|
||||
assert(RD->getDeclContext() == D->getDeclContext() &&
|
||||
@ -342,6 +343,12 @@ StringRef CGDebugInfo::getClassName(const RecordDecl *RD) {
|
||||
// associate typedef mangled in if they have one.
|
||||
Name = TND->getName();
|
||||
|
||||
// Give lambdas a display name based on their name mangling.
|
||||
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
|
||||
if (CXXRD->isLambda())
|
||||
return internString(
|
||||
CGM.getCXXABI().getMangleContext().getLambdaString(CXXRD));
|
||||
|
||||
if (!Name.empty()) {
|
||||
SmallString<256> UnnamedType("<unnamed-type-");
|
||||
UnnamedType += Name;
|
||||
|
@ -100,7 +100,7 @@ int main(int argc, char* argv[], char* arge[]) {
|
||||
// MSVC-SAME: )
|
||||
// MSVC: [[TYPE_OF_FOUR]] = distinct !DICompositeType
|
||||
// MSVC-SAME: tag: DW_TAG_class_type
|
||||
// MSVC-NOT: name:
|
||||
// MSVC-SAME: name: "<lambda_0>"
|
||||
// MSVC-SAME: identifier: ".?AV<lambda_0>@?0??main@@9@"
|
||||
// MSVC-SAME: )
|
||||
|
||||
|
@ -1,17 +1,26 @@
|
||||
// RUN: %clang_cc1 %s -gcodeview -debug-info-kind=line-tables-only -S \
|
||||
// RUN: -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 %s -triple x86_64-windows-msvc -gcodeview
|
||||
// RUN: -debug-info-kind=line-tables-only -emit-llvm -o - | FileCheck %s
|
||||
// Checks that clang with "-gline-tables-only" with CodeView emits some debug
|
||||
// info for variables and types when they appear in function scopes.
|
||||
|
||||
namespace NS {
|
||||
struct C {
|
||||
void m() {}
|
||||
// Test externally visible lambda.
|
||||
void lambda2() { []() {}(); }
|
||||
|
||||
// Test naming for function parameters.
|
||||
void lambda_params(int x = [](){ return 0; }(), int y = [](){ return 1; }()) {}
|
||||
};
|
||||
void f() {}
|
||||
}
|
||||
|
||||
// Test non- externally visible lambda.
|
||||
auto lambda1 = []() { return 1; };
|
||||
|
||||
NS::C c;
|
||||
|
||||
|
||||
void test() {
|
||||
// CHECK: !DISubprogram(name: "f", scope: ![[NS:[0-9]+]],
|
||||
// CHECK-SAME: type: ![[F:[0-9]+]]
|
||||
@ -21,10 +30,30 @@ void test() {
|
||||
NS::f();
|
||||
|
||||
// CHECK: ![[M:[0-9]+]] = distinct !DISubprogram(name: "m", scope: ![[C:[0-9]+]],
|
||||
// CHECK-SAME: type: ![[MTYPE:[0-9]+]]
|
||||
// CHECK-SAME: type: ![[MTYPE:[0-9]+]],
|
||||
// CHECK: ![[C]] = !DICompositeType(tag: DW_TAG_structure_type, name: "C",
|
||||
// CHECK-SAME: flags: DIFlagFwdDecl
|
||||
// CHECK-NOT: identifier
|
||||
// CHECK: ![[MTYPE]] = !DISubroutineType({{.*}}types: !{{.*}})
|
||||
c.m();
|
||||
|
||||
// CHECK: !DISubprogram(name: "operator()", scope: ![[LAMBDA0:[0-9]+]],
|
||||
// CHECK: ![[LAMBDA0]] = !DICompositeType(tag: DW_TAG_class_type,
|
||||
// CHECK-SAME: name: "<lambda_0>",
|
||||
// CHECK-SAME: flags: DIFlagFwdDecl
|
||||
lambda1();
|
||||
|
||||
// CHECK: !DISubprogram(name: "operator()", scope: ![[LAMBDA1_1:[0-9]+]],
|
||||
// CHECK: ![[LAMBDA1_1]] = !DICompositeType(tag: DW_TAG_class_type,
|
||||
// CHECK-SAME: name: "<lambda_1_1>",
|
||||
// CHECK: !DISubprogram(name: "operator()", scope: ![[LAMBDA2_1:[0-9]+]],
|
||||
// CHECK: ![[LAMBDA2_1]] = !DICompositeType(tag: DW_TAG_class_type,
|
||||
// CHECK-SAME: name: "<lambda_2_1>",
|
||||
c.lambda_params();
|
||||
|
||||
// CHECK: !DISubprogram(name: "operator()", scope: ![[LAMBDA1:[0-9]+]],
|
||||
// CHECK: ![[LAMBDA1]] = !DICompositeType(tag: DW_TAG_class_type,
|
||||
// CHECK-SAME: name: "<lambda_1>",
|
||||
// CHECK-SAME: flags: DIFlagFwdDecl
|
||||
c.lambda2();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user