-
-
Notifications
You must be signed in to change notification settings - Fork 265
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
add debug info for function parameter types #4804
Conversation
e6d3c58
to
03031a9
Compare
gen/dibuilder.cpp
Outdated
auto ditype = CreateTypeDescription(arg->type); | ||
if (arg->byref) { | ||
ditype = DBuilder.createPointerType(ditype, target.ptrsize * 8, 0, llvm::None, | ||
processDIName((type->toPrettyChars(true) + llvm::StringRef("*")).str())); |
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.
arg->byref
might be set for non-D-refs. I think the only robust way would be to use IrFuncTyArg::parametersIdx
and look up the AST param.
Also note that there's a DBuilder.createReferenceType()
; used in e.g. DIBuilder::EmitLocalVariable()
. But a struct this
needs to be represented as a pointer, not a ref, see comment in that function...
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.
arg->byref
might be set for non-D-refs. I think the only robust way would be to useIrFuncTyArg::parametersIdx
and look up the AST param.
It's totally unclear to me what these new param DIs are used for (as inside a function, we do have DIs for the params, but for their variable storage in memory, just like for locals, so not tied to the raw IR param). Maybe IrFuncTyArg::byref
is better than the frontend ref-ness indeed - with a likely exception for byval
params though (IrFuncTyArg::isByVal()
) I guess.
Edit: Probably best to check what clang emits (in 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.
Interesting: https://cpp.godbolt.org/z/x83nbd4Eh
; Large foo(Large l, Large &, NonPOD) { return l; }
define linkonce_odr dso_local void @S::foo(Large, Large&, NonPOD)(ptr dead_on_unwind noalias writable sret(%struct.Large) align 4 %agg.result, ptr noundef nonnull align 1 dereferenceable(1) %this, ptr noundef byval(%struct.Large) align 8 %l, ptr noundef nonnull align 4 dereferenceable(32) %0, ptr noundef %1) comdat align 2 !dbg !46 {
…
!46 = distinct !DISubprogram(name: "foo", linkageName: "S::foo(Large, Large&, NonPOD)", scope: !25, file: !4, line: 11, type: !28, scopeLine: 11, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, declaration: !27, retainedNodes: !23)
!28 = !DISubroutineType(types: !29)
!29 = !{!30, !36, !30, !37, !3}
!3 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "NonPOD", file: !4, line: 5, size: 32, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !5, identifier: "_ZTS6NonPOD")
!30 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Large", file: !4, line: 1, size: 256, flags: DIFlagTypePassByValue, elements: !31, identifier: "_ZTS5Large")
!36 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !25, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
!37 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !30, size: 64)
So clang uses the frontend signature and types, only adding the implicit this
pointer (with extra flags) - no sret pointer. And the types and ref-ness is determined from the AST alone as well - the IR function has 5 pointer IR params, but the function-type-DI only has 4 - implicit this
(pointer), Large l
(value), Large&
(ref) and NonPOD
(value).
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.
I've had a go at reworking this accordingly and pushed a commit.
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.
Thanks @kinke , that makes it a bit simpler again, i.e. no dependency on the IR. It doesn't show some hidden parameters (e.g. _arguments), but I'm not sure if that's good or bad.
The new version works with mago, too. I had some troubles also getting the struct members to work, because
- sometimes the struct type is returned when querying IDiaSymbol instead of a pointer to the struct.
- there seem to be conflicting debug information regarding the calling convention depending on how the symbol is accessed.
I don't see how this is caused by the emitted debug symbols, as it looks correct in a dump of the debug symbols. I have added some workarounds to mago.
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.
It's totally unclear to me what these new param DIs are used for
The VS debugger seems to need this information to populate the parameter types and values in the call stack.
Mago uses the function type to find the correct overload of the __debug*
functions and verifies the signature so that it can call the fucntion in the debugged process. Indeed, this could also check debug info for local variables (not sure you can easily distinguish between function arguments and locals), but it seems more complicated.
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.
Thanks @kinke , that makes it a bit simpler again, i.e. no dependency on the IR.
Yeah as I brought you on the wrong (IR) track, I figured I better 'fix' it again. :)
It doesn't show some hidden parameters (e.g. _arguments), but I'm not sure if that's good or bad.
Same here.
The new version works with mago, too. I had some troubles also getting the struct members to work, because
* sometimes the struct type is returned when querying IDiaSymbol instead of a pointer to the struct. * there seem to be conflicting debug information regarding the calling convention depending on how the symbol is accessed.
I don't see how this is caused by the emitted debug symbols, as it looks correct in a dump of the debug symbols. I have added some workarounds to mago.
clang uses an abundance of flags (DIFlagTypePassByReference | DIFlagNonTrivial
, DIFlagTypePassByValue
), that might be required/helpful in some circumstances. And I haven't quickly found a way to add the extra 'this' pointer flags, so I left that as a TODO comment.
gen/dibuilder.cpp
Outdated
if (fd) { | ||
Type *pointeeType = nullptr; | ||
if (auto parentAggregate = fd->isThis()) { | ||
pointeeType = parentAggregate->type; |
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.
My bad - this works for structs, but not for classes.
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.
Fix amended, incl. 'object-pointer' and 'artificial' flags.
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.
Thanks and sorry for the delay. The previous version already worked for me for classes, too.
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.
Np at all, my bad anyway, plus I didn't get to it sooner either. - FWIW, the previous version emitted an additional indirection for classes, so maybe you can get rid of a workaround in mago now.
A couple of days ago I added support to mago to evaluate the
__debugOverview
,__debugExpanded
and__debugStringview
hooks as free functions instead of struct members (see https://rainers.github.io/visuald/visuald/Debugging.html#customization). Apart from allowing to add debug visualizers for library types without editing the source, I hoped to also have LDC support this feature even though it omits class and struct members in the debug info. Here's a tiny example:Unfortunately, LDC omits the function parameters from the function type, but they are needed for overload resolution. This a small patch to add these. It also ticks off one item of #1716 as the call stack now displays parameter types and values.
While mago supports passing the argument as a pointer or a reference, the latter doesn't work with LDC as the ref argument is typed as value. Is this removed somewhere in LDC if the ABI passes the value by reference anyway?