On 25.07.2018 15:41, paul.robinson@sony.com wrote:Is it possible to emit DWARF statements, so that in the debugger the
parameter _param is hidden and the visibility is a and b, without a
_param-> prefix ?
It's certainly possible in LLVM IR. @llvm.dbg.declare and so on can
associate arbitrary Values in a function with whatever name you want.
DWARF expressions are certainly powerful enough to describe this.
I am not so sure about this now, after I tried this today and yesterday with limited success.
The main problem I think is, that_param-> points to a location, that isn't a fixed offset relative to the stack pointer.
When I run my IR code through llc, llc was unable to provide a location for the debugger. This might be more a limitation of llvm than of DWARF though.
Here is part of a DWARF dump with my two fake formal parameters. But as you can see the DW_AT_location is missing, which leads to problems in gdb and lldb:
<2><74>: Abbrev Number: 6 (DW_TAG_formal_parameter)
<75> DW_AT_location : 2 byte block: 91 68 (DW_OP_fbreg: -24)
<78> DW_AT_name : (indirect string, offset: 0xfd): _param
<7c> DW_AT_type : <0xf5>
<80> DW_AT_artificial : 1
<2><80>: Abbrev Number: 7 (DW_TAG_formal_parameter)
<81> DW_AT_name : (indirect string, offset: 0x104): name
<85> DW_AT_decl_file : 2
<86> DW_AT_decl_line : 16
<87> DW_AT_type : <0x11b>
<8b> DW_AT_artificial : 1
<2><8b>: Abbrev Number: 7 (DW_TAG_formal_parameter)
<8c> DW_AT_name : (indirect string, offset: 0x112): version
<90> DW_AT_decl_file : 2
<91> DW_AT_decl_line : 17
<92> DW_AT_type : <0x130>
<96> DW_AT_artificial : 1
This information relates to this .ll snippet created from my compiler (see below for full glory IR):
%_param.addr = alloca %"struct.Hello::p.printName:version:"*, align 8
%0 = getelementptr inbounds %"struct.Hello::p.printName:version:", %"struct.Hello::p.printName:version:"* %_param,
i32 0, i32 0
call void @llvm.dbg.declare(metadata i8** %0, metadata !32, metadata !DIExpression()), !dbg !34
%1 = getelementptr inbounds %"struct.Hello::p.printName:version:", %"struct.Hello::p.printName:version:"* %_param,
i32 0, i32 1
call void @llvm.dbg.declare(metadata i32* %1, metadata !33, metadata !DIExpression()), !dbg !35
!32 = !DILocalVariable(name: "name", arg: 4, scope: !21, file: !3, line: 22, type: !29)
!33 = !DILocalVariable(name: "version", arg: 5, scope: !21, file: !3, line: 23, type: !11)
!34 = !DILocation(line: 22, column: 29, scope: !21)
!35 = !DILocation(line: 23, column: 35, scope: !21)
I am not sure, if I can compute the DW_AT_location for llvm, but I guess that's probably what I will try to do next.
But it looks like you're trying to convince Clang itself to do that.
That's likely to be harder since it's not exactly a natural C mapping;
I suspect a lot depends on just where you're doing your ABI lowering.
Also depends on whether you want your debugger to be able to call these
functions.
Until recently I believed, that because lldb uses clang JIT to evaluate expressions, that when lldb uses my clang to evaluate "a", the code would be generated for "_param->a" and that lldb would access the correct value. I lost a little confidence in this though.
My guess is that you want to describe the formal parameter as artificial,
using the proper struct description, so that calls work correctly.
Then create local variables whose storage locations work indirectly off
the (described as artificial) pointer parameter.
If I create local storage locations, then wouldn't the debugger see stale copied information in cases where the function code modifies an argument ?
foo( int a)
{
++a;
}
is really
foo( struct { int a; } *_param)
{
++_param->a;
}
but with alloca:
foo( struct { int a; } *_param)
{
int a;
a = _param->a;
++_param->a;
// debug: p a gives ???
}
Seeing stale information would be bad.
Whether you get your modified front-end to do this, or hack up the
backend, up to you. The question was *can* it be done, and the answer
to that is clearly yes.
--paulr
Actually, currently I am doing both. 
Ciao
Nat!
Either way you're probably more likely to get a good response if you
ask the question on the cfe-dev mailing list.
Cheers.
Tim.
_______________________________________________
LLVM Developers mailing list
llvm-dev@lists.llvm.org
llvm-dev Info Page
; ModuleID = 'reduced.m'
source_filename = "reduced.m"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
%struct.anon = type { i32, i32 }
%struct._mulle_objc_method = type { i32, i8*, i8*, i32, i8* }
%struct._mulle_objc_loadclass = type { i32, i8*, i32, i32, i8*, i32, i32, i32, %struct._mulle_objc_ivarlist*, %struct._mulle_objc_methodlist*, %struct._mulle_objc_methodlist*, %struct._mulle_objc_propertylist*, %struct._mulle_objc_protocollist*, i32*, i8* }
%struct._mulle_objc_ivarlist = type opaque
%struct._mulle_objc_methodlist = type opaque
%struct._mulle_objc_propertylist = type { i32, [0 x %struct._mulle_objc_property] }
%struct._mulle_objc_property = type { i32, i32, i8*, i8*, i32, i32, i32 }
%struct._mulle_objc_protocollist = type { %struct._mulle_objc_protocollist*, i64, [0 x %struct._mulle_objc_protocol] }
%struct._mulle_objc_protocol = type { i32, i8* }
%"struct.Hello::p.printName:version:" = type { i8*, i32 }
@__mulle_objc_objccompilerinfo = global %struct.anon { i32 12, i32 0 }, align 4, !dbg !0
@OBJC_METH_VAR_NAME_ = private unnamed_addr constant [19 x i8] c"printName:version:\00", align 1
@OBJC_METH_VAR_TYPE_ = private unnamed_addr constant [14 x i8] c"v28@0:8*16I24\00", align 1
@OBJC_CLASS_NAME_ = private unnamed_addr constant [6 x i8] c"Hello\00", align 1
@OBJC_CLASS_METHODS_Hello = private global { i32, i8*, [1 x %struct._mulle_objc_method] } { i32 1, i8* null, [1 x %struct._mulle_objc_method] [%struct._mulle_objc_method { i32 -1285604266, i8* getelementptr inbounds ([19 x i8], [19 x i8]* @OBJC_METH_VAR_NAME_, i32 0, i32 0), i8* getelementptr inbounds ([14 x i8], [14 x i8]* @OBJC_METH_VAR_TYPE_, i32 0, i32 0), i32 0, i8* bitcast (void (i8*, i32, %"struct.Hello::p.printName:version:"*)* @"+[Hello printName:version:]" to i8*) }] }, section "_DATA,__cls_meth,regular,no_dead_strip", align 4
@OBJC_DEBUG_INFO_ = private unnamed_addr constant [10 x i8] c"reduced.m\00", align 1
@OBJC_CLASS_Hello = private global %struct._mulle_objc_loadclass { i32 1438848191, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0), i32 298441816, i32 0, i8* null, i32 0, i32 -1, i32 0, %struct._mulle_objc_ivarlist* null, %struct._mulle_objc_methodlist* bitcast ({ i32, i8*, [1 x %struct._mulle_objc_method] }* @OBJC_CLASS_METHODS_Hello to %struct._mulle_objc_methodlist*), %struct._mulle_objc_methodlist* null, %struct._mulle_objc_propertylist* null, %struct._mulle_objc_protocollist* null, i32* null, i8* getelementptr inbounds ([10 x i8], [10 x i8]* @OBJC_DEBUG_INFO_, i32 0, i32 0) }, section "__DATA,__class,regular,no_dead_strip", align 4
@OBJC_HASHNAME_ = private global [1 x i8] zeroinitializer, section "__DATA,__module_info,regular,no_dead_strip", align 4
@OBJC_HASHNAME_Hello = private global [6 x i8] c"Hello\00", section "__DATA,__module_info,regular,no_dead_strip", align 4
@"OBJC_HASHNAME_printName:version:" = private global [19 x i8] c"printName:version:\00", section "__DATA,__module_info,regular,no_dead_strip", align 4
@llvm.compiler.used = appending global [9 x i8*] [i8* getelementptr inbounds ([19 x i8], [19 x i8]* @OBJC_METH_VAR_NAME_, i32 0, i32 0), i8* getelementptr inbounds ([14 x i8], [14 x i8]* @OBJC_METH_VAR_TYPE_, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0), i8* bitcast ({ i32, i8*, [1 x %struct._mulle_objc_method] }* @OBJC_CLASS_METHODS_Hello to i8*), i8* getelementptr inbounds ([10 x i8], [10 x i8]* @OBJC_DEBUG_INFO_, i32 0, i32 0), i8* bitcast (%struct._mulle_objc_loadclass* @OBJC_CLASS_Hello to i8*), i8* getelementptr inbounds ([1 x i8], [1 x i8]* @OBJC_HASHNAME_, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @OBJC_HASHNAME_Hello, i32 0, i32 0), i8* getelementptr inbounds ([19 x i8], [19 x i8]* @"OBJC_HASHNAME_printName:version:", i32 0, i32 0)], section "llvm.metadata"
; Function Attrs: noinline nounwind optnone uwtable
define internal void @"+[Hello printName:version:]"(i8* nonnull %self, i32 zeroext %_cmd, %"struct.Hello::p.printName:version:"* %_param) #0 !dbg !21 {
entry:
%self.addr = alloca i8*, align 8
%_cmd.addr = alloca i32, align 4
%_param.addr = alloca %"struct.Hello::p.printName:version:"*, align 8
%0 = getelementptr inbounds %"struct.Hello::p.printName:version:", %"struct.Hello::p.printName:version:"* %_param, i32 0, i32 0
call void @llvm.dbg.declare(metadata i8** %0, metadata !32, metadata !DIExpression()), !dbg !34
%1 = getelementptr inbounds %"struct.Hello::p.printName:version:", %"struct.Hello::p.printName:version:"* %_param, i32 0, i32 1
call void @llvm.dbg.declare(metadata i32* %1, metadata !33, metadata !DIExpression()), !dbg !35
store i8* %self, i8** %self.addr, align 8
call void @llvm.dbg.declare(metadata i8** %self.addr, metadata !36, metadata !DIExpression()), !dbg !38
store i32 %_cmd, i32* %_cmd.addr, align 4
call void @llvm.dbg.declare(metadata i32* %_cmd.addr, metadata !39, metadata !DIExpression()), !dbg !38
store %"struct.Hello::p.printName:version:"* %_param, %"struct.Hello::p.printName:version:"** %_param.addr, align 8
call void @llvm.dbg.declare(metadata %"struct.Hello::p.printName:version:"** %_param.addr, metadata !41, metadata !DIExpression()), !dbg !38
ret void, !dbg !47
}
; Function Attrs: nounwind readnone speculatable
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { nounwind readnone speculatable }
!llvm.module.flags = !{!13, !14, !15, !16, !17, !18, !19}
!llvm.dbg.cu = !{!2}
!llvm.ident = !{!20}
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
!1 = distinct !DIGlobalVariable(name: "__mulle_objc_objccompilerinfo", scope: !2, file: !3, line: 5, type: !8, isLocal: false, isDefinition: true)
!2 = distinct !DICompileUnit(language: DW_LANG_ObjC, file: !3, producer: "mulle-clang 6.0.0.4 (runtime-load-version: 12) clang version 6.0.0 (based on LLVM 6.0.0)", isOptimized: false, runtimeVersion: 1848, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !7)
!3 = !DIFile(filename: "reduced.m", directory: "/tmp/yyy")
!4 = !{}
!5 = !{!6}
!6 = !DICompositeType(tag: DW_TAG_structure_type, name: "Hello", scope: !3, file: !3, line: 12, flags: DIFlagObjcClassComplete, elements: !4, runtimeLang: DW_LANG_ObjC)
!7 = !{!0}
!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !3, line: 1, size: 64, elements: !9)
!9 = !{!10, !12}
!10 = !DIDerivedType(tag: DW_TAG_member, name: "load", scope: !8, file: !3, line: 3, baseType: !11, size: 32)
!11 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
!12 = !DIDerivedType(tag: DW_TAG_member, name: "runtime", scope: !8, file: !3, line: 4, baseType: !11, size: 32, offset: 32)
!13 = !{i32 1, !"Objective-C Version", i32 1848}
!14 = !{i32 1, !"Objective-C Image Info Version", i32 0}
!15 = !{i32 1, !"Objective-C Image Info Section", !"__DATA, __image_info,regular,no_dead_strip"}
!16 = !{i32 4, !"Objective-C Garbage Collection", i32 0}
!17 = !{i32 2, !"Dwarf Version", i32 4}
!18 = !{i32 2, !"Debug Info Version", i32 3}
!19 = !{i32 1, !"wchar_size", i32 4}
!20 = !{!"mulle-clang 6.0.0.4 (runtime-load-version: 12) clang version 6.0.0 (based on LLVM 6.0.0)"}
!21 = distinct !DISubprogram(name: "+[Hello printName:version:]", scope: !3, file: !3, line: 22, type: !22, isLocal: true, isDefinition: true, scopeLine: 22, flags: DIFlagPrototyped, isOptimized: false, unit: !2, variables: !31)
!22 = !DISubroutineType(types: !23)
!23 = !{null, !24, !27, !29, !11}
!24 = !DIDerivedType(tag: DW_TAG_typedef, name: "Class", file: !3, line: 5, baseType: !25, flags: DIFlagArtificial | DIFlagObjectPointer)
!25 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !26, size: 64)
!26 = !DICompositeType(tag: DW_TAG_structure_type, name: "objc_class", file: !3, flags: DIFlagFwdDecl)
!27 = !DIDerivedType(tag: DW_TAG_typedef, name: "SEL", file: !3, line: 5, baseType: !28, flags: DIFlagArtificial)
!28 = !DICompositeType(tag: DW_TAG_structure_type, name: "objc_selector", file: !3, flags: DIFlagFwdDecl)
!29 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !30, size: 64)
!30 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
!31 = !{!32, !33}
!32 = !DILocalVariable(name: "name", arg: 4, scope: !21, file: !3, line: 22, type: !29)
!33 = !DILocalVariable(name: "version", arg: 5, scope: !21, file: !3, line: 23, type: !11)
!34 = !DILocation(line: 22, column: 29, scope: !21)
!35 = !DILocation(line: 23, column: 35, scope: !21)
!36 = !DILocalVariable(name: "self", arg: 1, scope: !21, type: !37, flags: DIFlagArtificial | DIFlagObjectPointer)
!37 = !DIDerivedType(tag: DW_TAG_typedef, name: "Class", file: !3, line: 5, baseType: !25)
!38 = !DILocation(line: 0, scope: !21)
!39 = !DILocalVariable(name: "_cmd", arg: 2, scope: !21, type: !40, flags: DIFlagArtificial)
!40 = !DIDerivedType(tag: DW_TAG_typedef, name: "SEL", file: !3, line: 5, baseType: !28)
!41 = !DILocalVariable(name: "_param", arg: 3, scope: !21, type: !42, flags: DIFlagArtificial)
!42 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !43, size: 64)
!43 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "p.printName:version:", file: !3, line: 22, size: 128, elements: !44)
!44 = !{!45, !46}
!45 = !DIDerivedType(tag: DW_TAG_member, name: "name", scope: !43, file: !3, line: 22, baseType: !29, size: 64)
!46 = !DIDerivedType(tag: DW_TAG_member, name: "version", scope: !43, file: !3, line: 23, baseType: !11, size: 32, offset: 64)
!47 = !DILocation(line: 25, column: 1, scope: !21)
Original .m
struct
{
unsigned int load;
unsigned int runtime;
} __mulle_objc_objccompilerinfo =
{
12,
0
};
@interface Hello
+ (void) printName:(char *) name
version:(unsigned int) version;
@end
@implementation Hello
+ (void) printName:(char *) name
version:(unsigned int) version;
{
}
@end