r330132 - [CodeView] Initial support for emitting S_THUNK32 symbols for compiler...
Brock Wyma via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 16 09:53:58 PDT 2018
Author: bwyma
Date: Mon Apr 16 09:53:57 2018
New Revision: 330132
URL: http://llvm.org/viewvc/llvm-project?rev=330132&view=rev
Log:
[CodeView] Initial support for emitting S_THUNK32 symbols for compiler...
When emitting CodeView debug information, compiler-generated thunk routines
should be emitted using S_THUNK32 symbols instead of S_GPROC32_ID symbols so
Visual Studio can properly step into the user code. This initial support only
handles standard thunk ordinals.
Differential Revision: https://reviews.llvm.org/D43838
Modified:
cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
cfe/trunk/lib/CodeGen/CGDebugInfo.h
cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
cfe/trunk/test/CodeGenCXX/debug-info-thunk.cpp
Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=330132&r1=330131&r2=330132&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Mon Apr 16 09:53:57 2018
@@ -3217,7 +3217,8 @@ llvm::DISubroutineType *CGDebugInfo::get
void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
SourceLocation ScopeLoc, QualType FnType,
- llvm::Function *Fn, CGBuilderTy &Builder) {
+ llvm::Function *Fn, bool CurFuncIsThunk,
+ CGBuilderTy &Builder) {
StringRef Name;
StringRef LinkageName;
@@ -3263,6 +3264,10 @@ void CGDebugInfo::EmitFunctionStart(Glob
// Artificial functions should not silently reuse CurLoc.
CurLoc = SourceLocation();
}
+
+ if (CurFuncIsThunk)
+ Flags |= llvm::DINode::FlagThunk;
+
unsigned LineNo = getLineNumber(Loc);
unsigned ScopeLine = getLineNumber(ScopeLoc);
Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.h?rev=330132&r1=330131&r2=330132&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.h (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.h Mon Apr 16 09:53:57 2018
@@ -366,7 +366,8 @@ public:
/// \param ScopeLoc The location of the function body.
void EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
SourceLocation ScopeLoc, QualType FnType,
- llvm::Function *Fn, CGBuilderTy &Builder);
+ llvm::Function *Fn, bool CurFnIsThunk,
+ CGBuilderTy &Builder);
/// Start a new scope for an inlined function.
void EmitInlineFunctionStart(CGBuilderTy &Builder, GlobalDecl GD);
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=330132&r1=330131&r2=330132&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Mon Apr 16 09:53:57 2018
@@ -1018,7 +1018,8 @@ void CodeGenFunction::StartFunction(Glob
ArgTypes.push_back(VD->getType());
QualType FnType = getContext().getFunctionType(
RetTy, ArgTypes, FunctionProtoType::ExtProtoInfo(CC));
- DI->EmitFunctionStart(GD, Loc, StartLoc, FnType, CurFn, Builder);
+ DI->EmitFunctionStart(GD, Loc, StartLoc, FnType, CurFn, CurFuncIsThunk,
+ Builder);
}
if (ShouldInstrumentFunction()) {
Modified: cfe/trunk/test/CodeGenCXX/debug-info-thunk.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/debug-info-thunk.cpp?rev=330132&r1=330131&r2=330132&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/debug-info-thunk.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/debug-info-thunk.cpp Mon Apr 16 09:53:57 2018
@@ -1,29 +1,277 @@
-// RUN: %clang_cc1 %s -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm -o - | FileCheck %s
-
-struct A {
- virtual void f();
-};
-
-struct B {
- virtual void f();
-};
-
-struct C : A, B {
- virtual void f();
-};
-
-void C::f() { }
-// CHECK: define {{.*}}void @_ZThn{{[48]}}_N1C1fEv
-// CHECK-SAME: !dbg ![[SP:[0-9]+]]
-// CHECK-NOT: {{ret }}
-// CHECK: = load{{.*}} !dbg ![[DBG:[0-9]+]]
-// CHECK-NOT: {{ret }}
-// CHECK: ret void, !dbg ![[DBG]]
+// RUN: %clang_cc1 %s -triple=x86_64-pc-windows-msvc -debug-info-kind=limited -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm -o - | FileCheck %s -check-prefix=ITANIUM
+//
+// Validate we emit a "DIFlagThunk" flag on DISubprogram entries for thunks.
+// This flag is used for emitting S_THUNK32 symbols for CodeView debugging.
+//
+// NOTE:
+// Because thunks are compiler generated and don't exist in the source, this
+// test is dependent upon the linkage name to identify the thunk. Any changes
+// in the name mangling may require this test to be updated.
//
-// CHECK: ![[SP]] = distinct !DISubprogram(linkageName: "_ZThn{{[48]}}_N1C1fEv"
-// CHECK-SAME: line: 15
-// CHECK-SAME: isDefinition: true
-// CHECK-SAME: DIFlagArtificial
-// CHECK-SAME: ){{$}}
+// NOTE:
+// The FileCheck directives below use CHECK-DAG because the thunks may not be
+// emitted in source order.
//
-// CHECK: ![[DBG]] = !DILocation(line: 0
+
+namespace Test1 {
+ struct A {
+ virtual void f();
+ };
+
+ struct B {
+ virtual void f();
+ };
+
+ struct C : A, B {
+ virtual void c();
+
+ virtual void f();
+ };
+
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f at C@Test1@@W7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk
+ void C::f() { }
+}
+
+namespace Test2 {
+ struct V1 { };
+ struct V2 : virtual V1 { };
+
+ struct A {
+ virtual V1 *f();
+ };
+
+ struct B : A {
+ virtual void b();
+
+ virtual V2 *f();
+ };
+
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f at B@Test2@@QEAAPEAUV1 at 2@XZ"{{.*}} flags: {{.*}}DIFlagThunk
+ V2 *B::f() { return 0; }
+}
+
+namespace Test3 {
+ struct A {
+ virtual void f();
+ };
+
+ struct B {
+ virtual void f();
+ };
+
+ struct __attribute__((visibility("protected"))) C : A, B {
+ virtual void c();
+
+ virtual void f();
+ };
+
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f at C@Test3@@W7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk
+ void C::f() { }
+}
+
+namespace Test4 {
+ struct A {
+ virtual void f();
+ };
+
+ struct B {
+ virtual void f();
+ };
+
+ namespace {
+ struct C : A, B {
+ virtual void c();
+ virtual void f();
+ };
+ }
+ void C::c() {}
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f at C@?A at Test4@@W7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk
+ void C::f() {}
+
+ // Force C::f to be used.
+ void f() {
+ C c;
+ c.f();
+ }
+}
+
+namespace Test5 {
+ struct X {
+ X();
+ X(const X&);
+ X &operator=(const X&);
+ ~X();
+ };
+
+ struct P {
+ P();
+ P(const P&);
+ ~P();
+ X first;
+ X second;
+ };
+
+ P getP();
+
+ struct Base1 {
+ int i;
+
+ virtual X f() { return X(); }
+ };
+
+ struct Base2 {
+ float real;
+
+ virtual X f() { return X(); }
+ };
+
+ struct Thunks : Base1, Base2 {
+ long l;
+
+ virtual X f();
+ };
+
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f at Thunks@Test5@@WBA at EAA?AUX at 2@XZ"{{.*}} flags: {{.*}}DIFlagThunk
+ X Thunks::f() { return X(); }
+}
+
+namespace Test6 {
+ struct X {
+ X();
+ X(const X&);
+ X &operator=(const X&);
+ ~X();
+ };
+
+ struct Small { short s; };
+ struct Large {
+ char array[1024];
+ };
+
+ class A {
+ protected:
+ virtual void foo() = 0;
+ };
+
+ class B : public A {
+ protected:
+ virtual void bar() = 0;
+ };
+
+ class C : public A {
+ protected:
+ virtual void baz(X, X&, _Complex float, Small, Small&, Large) = 0;
+ };
+
+ class D : public B,
+ public C {
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?foo at D@Test6@@G7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk
+ void foo() {}
+ void bar() {}
+ void baz(X, X&, _Complex float, Small, Small&, Large);
+ };
+
+ void D::baz(X, X&, _Complex float, Small, Small&, Large) { }
+
+ void testD() { D d; }
+}
+
+namespace Test7 {
+ struct A { virtual void foo(); };
+ struct B { virtual void foo(); };
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?foo at C@Test7@@W7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk
+ struct C : A, B { void foo() {} };
+
+ // Test later.
+ void test() {
+ C c;
+ }
+}
+
+namespace Test8 {
+ struct A { virtual A* f(); };
+ struct B : virtual A { virtual A* f(); };
+ struct C : B { virtual C* f(); };
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f at C@Test8@@QEAAPEAUA at 2@XZ"{{.*}} flags: {{.*}}DIFlagThunk
+ C* C::f() { return 0; }
+}
+
+namespace Test9 {
+ struct B1 {
+ virtual B1 &foo1();
+ };
+ struct Pad1 {
+ virtual ~Pad1();
+ };
+ struct Proxy1 : Pad1, B1 {
+ virtual ~Proxy1();
+ };
+ struct D : virtual Proxy1 {
+ virtual ~D();
+ virtual D &foo1();
+ };
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?foo1 at D@Test9@@$4PPPPPPPE at A@EAAAEAUB1 at 2@XZ"{{.*}} flags: {{.*}}DIFlagThunk
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?foo1 at D@Test9@@$4PPPPPPPE at A@EAAAEAU12 at XZ"{{.*}} flags: {{.*}}DIFlagThunk
+ D& D::foo1() {
+ return *this;
+ }
+}
+
+namespace Test10 {
+ class A {
+ virtual void f();
+ };
+ class B {
+ virtual void f();
+ };
+ class C : public A, public B {
+ virtual void f();
+ };
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f at C@Test10@@G7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk
+ void C::f() {
+ }
+}
+
+namespace Test11 {
+ class A {
+ public:
+ virtual void f();
+ };
+
+ void test() {
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "??_9A at Test11@@$BA at AA"{{.*}} flags: {{.*}}DIFlagThunk
+ void (A::*p)() = &A::f;
+ }
+}
+
+namespace Test12 {
+ struct A {
+ virtual void f();
+ };
+
+ struct B {
+ virtual void f();
+ };
+
+ struct C : A, B {
+ virtual void f();
+ };
+
+ void C::f() { }
+ // ITANIUM: define {{.*}}void @_ZThn{{[48]}}_N6Test121C1fEv
+ // ITANIUM-SAME: !dbg ![[SP:[0-9]+]]
+ // ITANIUM-NOT: {{ret }}
+ // ITANIUM: = load{{.*}} !dbg ![[DBG:[0-9]+]]
+ // ITANIUM-NOT: {{ret }}
+ // ITANIUM: ret void, !dbg ![[DBG]]
+ //
+ // ITANIUM: ![[SP]] = distinct !DISubprogram(linkageName: "_ZThn{{[48]}}_N6Test121C1fEv"
+ // ITANIUM-SAME: line: 261
+ // ITANIUM-SAME: isDefinition: true
+ // ITANIUM-SAME: DIFlagArtificial
+ // ITANIUM-SAME: DIFlagThunk
+ // ITANIUM-SAME: ){{$}}
+ //
+ // ITANIUM: ![[DBG]] = !DILocation(line: 0
+}
More information about the cfe-commits
mailing list