-
Notifications
You must be signed in to change notification settings - Fork 14.6k
[clang] Fix clang debug info generation for unprtototyped function #150022
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-debuginfo @llvm/pr-subscribers-backend-risc-v Author: Georgiy Samoylov (sga-sc) ChangesConsider this declaration:
This function is described in LLVM with Judging by this comment all such functions are treated like functions with variadic number of parameters. When we want to emit debug info we have to know function that we calling. In method getCalledFunction() we compare two types of function:
If they differ we get The only thing they differ is: lhs function is variadic, but rhs function isn't Reason of this difference is that under RISC-V there is no overridden function that tells us about treating functions with no parameters. Default function always return This patch overrides this function for RISC-V Full diff: https://github.com/llvm/llvm-project/pull/150022.diff 3 Files Affected:
diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp
index e3232b61a693c..6c2ce5c96ce4a 100644
--- a/clang/lib/CodeGen/Targets/RISCV.cpp
+++ b/clang/lib/CodeGen/Targets/RISCV.cpp
@@ -842,6 +842,11 @@ class RISCVTargetCodeGenInfo : public TargetCodeGenInfo {
Fn->addFnAttr("interrupt", Kind);
}
+
+ bool isNoProtoCallVariadic(const CallArgList &,
+ const FunctionNoProtoType *) const override {
+ return true;
+ }
};
} // namespace
diff --git a/clang/test/CodeGen/RISCV/debug-info-emit-func-decl.c b/clang/test/CodeGen/RISCV/debug-info-emit-func-decl.c
new file mode 100644
index 0000000000000..e580cb2702047
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/debug-info-emit-func-decl.c
@@ -0,0 +1,27 @@
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv64 -debug-info-kind=limited -dwarf-version=4 -debugger-tuning=gdb -O2 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-RV64
+// RUN: %clang_cc1 -triple riscv64 -debug-info-kind=limited -dwarf-version=4 -debugger-tuning=lldb -O2 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-RV64
+// RUN: %clang_cc1 -triple riscv64 -debug-info-kind=limited -dwarf-version=5 -O2 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-RV64
+
+// RUN: %clang_cc1 -triple riscv32 -debug-info-kind=limited -dwarf-version=4 -debugger-tuning=gdb -O2 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-RV32
+// RUN: %clang_cc1 -triple riscv32 -debug-info-kind=limited -dwarf-version=4 -debugger-tuning=lldb -O2 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-RV32
+// RUN: %clang_cc1 -triple riscv32 -debug-info-kind=limited -dwarf-version=5 -O2 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-RV32
+
+// CHECK-RV64: declare !dbg ![[FOO:[0-9]+]] void @foo(...) local_unnamed_addr #[[ATTR0:[0-9]+]]
+// CHECK-RV32: declare !dbg ![[FOO:[0-9]+]] void @foo(...) local_unnamed_addr #[[ATTR0:[0-9]+]]
+void foo();
+
+// CHECK-RV64: declare !dbg ![[BAR:[0-9]+]] void @bar() local_unnamed_addr #[[ATTR0:[0-9]+]]
+// CHECK-RV32: declare !dbg ![[BAR:[0-9]+]] void @bar() local_unnamed_addr #[[ATTR0:[0-9]+]]
+void bar(void);
+
+// CHECK-RV64: declare !dbg ![[BAZ:[0-9]+]] void @baz(i32 noundef signext, ...) local_unnamed_addr #[[ATTR0:[0-9]+]]
+// CHECK-RV32: declare !dbg ![[BAZ:[0-9]+]] void @baz(i32 noundef, ...) local_unnamed_addr #[[ATTR0:[0-9]+]]
+void baz(int a, ...);
+
+int main() {
+ foo();
+ bar();
+ baz(1);
+ return 0;
+}
diff --git a/clang/test/CodeGen/RISCV/debug-info-emit-func-decl.cpp b/clang/test/CodeGen/RISCV/debug-info-emit-func-decl.cpp
new file mode 100644
index 0000000000000..48f5540b4be78
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/debug-info-emit-func-decl.cpp
@@ -0,0 +1,27 @@
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv64 -debug-info-kind=limited -dwarf-version=4 -debugger-tuning=gdb -O2 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-RV64
+// RUN: %clang_cc1 -triple riscv64 -debug-info-kind=limited -dwarf-version=4 -debugger-tuning=lldb -O2 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-RV64
+// RUN: %clang_cc1 -triple riscv64 -debug-info-kind=limited -dwarf-version=5 -O2 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-RV64
+
+// RUN: %clang_cc1 -triple riscv32 -debug-info-kind=limited -dwarf-version=4 -debugger-tuning=gdb -O2 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-RV32
+// RUN: %clang_cc1 -triple riscv32 -debug-info-kind=limited -dwarf-version=4 -debugger-tuning=lldb -O2 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-RV32
+// RUN: %clang_cc1 -triple riscv32 -debug-info-kind=limited -dwarf-version=5 -O2 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-RV32
+
+// CHECK-RV64: declare !dbg ![[FOO:[0-9]+]] void @_Z3foov() local_unnamed_addr #[[ATTR0:[0-9]+]]
+// CHECK-RV32: declare !dbg ![[FOO:[0-9]+]] void @_Z3foov() local_unnamed_addr #[[ATTR0:[0-9]+]]
+void foo();
+
+// CHECK-RV64: declare !dbg ![[BAR:[0-9]+]] void @_Z3barv() local_unnamed_addr #[[ATTR0:[0-9]+]]
+// CHECK-RV32: declare !dbg ![[BAR:[0-9]+]] void @_Z3barv() local_unnamed_addr #[[ATTR0:[0-9]+]]
+void bar(void);
+
+// CHECK-RV64: declare !dbg ![[BAZ:[0-9]+]] void @_Z3baziz(i32 noundef signext, ...) local_unnamed_addr #[[ATTR0:[0-9]+]]
+// CHECK-RV32: declare !dbg ![[BAZ:[0-9]+]] void @_Z3baziz(i32 noundef, ...) local_unnamed_addr #[[ATTR0:[0-9]+]]
+void baz(int a, ...);
+
+int main() {
+ foo();
+ bar();
+ baz(1);
+ return 0;
+}
|
@kito-cheng @lenary @topperc guys, could you take a look, please? |
I'm not sure a no-prototype call is the same as a variadic call on RISC-V, but I'm not sure. Note that the rules for passing variadic arguments are slightly different to passing non-variadic arguments:
I'm not sure the impact treating no-prototype functions as variadic in debug info would have, presumably we might end up looking in the wrong registers for argument values? |
So according to the standard, unprototyped function calls are not variadic: if you try to call a variadic function using an unprototyped function, the behavior is formally undefined. On some targets, for some function signatures, it might appear to work. On x86 specifically, we have a minor compatibility hack: if you call an unprototyped function with certain arguments, we emit it as if it was variadic, so the backend knows to set "al". This makes calling a variadic function through an unprototyped signature work in some cases. But this is just a best-effort thing, to try to make broken code appear to work. And it isn't portable. CGDebugInfo should probably be using something like |
4822a7b
to
765d836
Compare
765d836
to
238b68d
Compare
✅ With the latest revision this PR passed the C/C++ code formatter. |
3807705
to
5d63792
Compare
@efriedma-quic Addressed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code change looks fine.
Are the tests just checking that there's !dbg
metadata attached to the function declarations? Do you really need 12 RUN lines to check that?
Declaration with llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp Lines 6364 to 6384 in 0a8ddd3
llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp Line 4817 in 0a8ddd3
So in this test I sort through these options and check that necessary declarations exist. Also there is a difference between the declaration of foo for C and C++ and little a difference between RISCV64 and RISCV32. In that way we get 12 RUN commands.
|
Having checks for different optimization levels and DWARF versions is probably fine... but a lot of those checks overlap with clang/test/CodeGenCXX/dbg-info-all-calls-described.cpp . Explicitly checking RV32 vs RV64 seems unproductive; this code isn't target-specific. |
eb24c47
to
1b80fdd
Compare
Ok, I see such test already exists. I added similar test for C |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
clang/lib/CodeGen/CGDebugInfo.cpp
Outdated
@@ -4805,7 +4805,8 @@ void CGDebugInfo::EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke, | |||
const FunctionDecl *CalleeDecl) { | |||
if (!CallOrInvoke) | |||
return; | |||
auto *Func = CallOrInvoke->getCalledFunction(); | |||
auto *Func = | |||
dyn_cast_or_null<llvm::Function>(CallOrInvoke->getCalledOperand()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, one minor adjustment: this can just be dyn_cast. CallOrInvoke->getCalledOperand()
will never return null for well-formed IR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed. Could you merge it, please?
1b80fdd
to
50d14a4
Compare
These have been XPASSing after #150022
…arm64 These have been XPASSing after llvm/llvm-project#150022
These have been un-XFAILed in `ebe6eba62580592af7065a36b22d929c15291e9a`, but require following Clang fix: #150022. So skip older compilers.
…rsions These have been un-XFAILed in `ebe6eba62580592af7065a36b22d929c15291e9a`, but require following Clang fix: llvm/llvm-project#150022. So skip older compilers.
Consider this declaration:
int foo();
This function is described in LLVM with
clang::FunctionNoProtoType
class. (See description)Judging by this comment all such functions are treated like functions with variadic number of parameters.
When we want to emit debug info we have to know function that we calling.
In method getCalledFunction() we compare two types of function:
If they differ we get
nullptr
and can't emit appropriate debug info.The only thing they differ is: lhs function is variadic, but rhs function isn't
Reason of this difference is that under RISC-V there is no overridden function that tells us about treating functions with no parameters. Default function always return
false
.This patch overrides this function for RISC-V