From 25e832940cb6fa76e0c365762f66c466a1e6eef3 Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Sat, 4 Jun 2022 22:14:02 +0200 Subject: [PATCH] llvmdbg: support for generating debug information for local/para varsyms Note that not all symbols are covered yet, because absolutevarsyms are not yet supported and those are e.g. used for function result aliases. Additionally, not all types are fully supported yet. --- compiler/llvm/aasmllvm.pas | 34 ++++++++++-- compiler/llvm/dbgllvm.pas | 106 +++++++++++++++++++++++++++++++++++-- rtl/inc/llvmintr.inc | 2 + 3 files changed, 134 insertions(+), 8 deletions(-) diff --git a/compiler/llvm/aasmllvm.pas b/compiler/llvm/aasmllvm.pas index e1df6104d2..b12b218b06 100644 --- a/compiler/llvm/aasmllvm.pas +++ b/compiler/llvm/aasmllvm.pas @@ -33,8 +33,13 @@ interface llvmbase; type + pllvmcallpara = ^tllvmcallpara; + { taillvm } taillvm = class(tai_cpu_abstract_sym) + const + callpdopernr = 3; + var llvmopcode: tllvmop; metadata: tai; @@ -145,6 +150,8 @@ interface procedure loadasmlist(opidx: longint; _asmlist: tasmlist); procedure loadcallingconvention(opidx: longint; calloption: tproccalloption); + function getcallpara(callparaindex: longint): pllvmcallpara; + procedure addinsmetadata(insmeta: tai); procedure landingpad_add_clause(op: tllvmop; def: tdef; kind: TAsmSymbol); @@ -220,10 +227,10 @@ interface top_const: (value: int64); top_undef : (); top_tai : (ai: tai); + top_local : (localsym: tsym); end; { parameter to an llvm call instruction } - pllvmcallpara = ^tllvmcallpara; tllvmcallpara = object def: tdef; alignment: shortint; @@ -560,6 +567,23 @@ implementation end; end; + function taillvm.getcallpara(callparaindex: longint): pllvmcallpara; + var + i: longint; + begin + for i:=0 to ops do + begin + if oper[i]^.typ=top_para then + begin + if callparaindex>=oper[i]^.paras.count then + internalerror(2022052611); + result:=pllvmcallpara(oper[i]^.paras[callparaindex]); + exit; + end; + end; + internalerror(2022052612); + end; + procedure taillvm.addinsmetadata(insmeta: tai); begin insmeta.next:=metadata; @@ -1204,7 +1228,7 @@ implementation loaddef(0,retsize); loadreg(1,dst); loadcallingconvention(2,cc); - loaddef(3,callpd); + loaddef(callpdopernr,callpd); loadsymbol(4,name,0); loadparas(5,paras); end; @@ -1217,7 +1241,7 @@ implementation loaddef(0,retsize); loadreg(1,dst); loadcallingconvention(2,cc); - loaddef(3,callpd); + loaddef(callpdopernr,callpd); loadreg(4,reg); loadparas(5,paras); end; @@ -1230,7 +1254,7 @@ implementation loaddef(0,retsize); loadreg(1,dst); loadcallingconvention(2,cc); - loaddef(3,callpd); + loaddef(callpdopernr,callpd); loadsymbol(4,name,0); loadparas(5,paras); loadsymbol(6,retlab,0); @@ -1245,7 +1269,7 @@ implementation loaddef(0,retsize); loadreg(1,dst); loadcallingconvention(2,cc); - loaddef(3,callpd); + loaddef(callpdopernr,callpd); loadreg(4,reg); loadparas(5,paras); loadsymbol(6,retlab,0); diff --git a/compiler/llvm/dbgllvm.pas b/compiler/llvm/dbgllvm.pas index 5ea362d390..ad4a317b98 100644 --- a/compiler/llvm/dbgllvm.pas +++ b/compiler/llvm/dbgllvm.pas @@ -77,13 +77,19 @@ interface flexicalblockfilemeta: THashSet; { lookup table for tstaticvarsym -> taillvmdecl } fstaticvarsymdecl: THashSet; + { lookup table for local/paravarsym -> metadata } + flocalvarsymmeta: THashSet; fcunode: tai_llvmspecialisedmetadatanode; fenums: tai_llvmunnamedmetadatanode; fretainedtypes: tai_llvmunnamedmetadatanode; fglobals: tai_llvmunnamedmetadatanode; { reusable empty expression node } - femptyexpression: tai_llvmspecialisedmetadatanode; + femptyexpression, + { reusable deref node } + fderefexpression : tai_llvmspecialisedmetadatanode; + + fllvm_dbg_addr_pd: tprocdef; function absolute_llvm_path(const s:tcmdstr):tcmdstr; protected @@ -104,6 +110,8 @@ interface procedure staticvarsym_set_decl(sym: tsym; decl: taillvmdecl); function staticvarsym_get_decl(sym: tsym): taillvmdecl; + function localvarsym_get_meta(sym: tsym; out is_new: boolean): tai_llvmspecialisedmetadatanode; + procedure appenddef_array_internal(list: TAsmList; fordef: tdef; eledef: tdef; lowrange, highrange: asizeint); function getabstractprocdeftypes(list: TAsmList; def:tabstractprocdef): tai_llvmbasemetadatanode; @@ -157,6 +165,7 @@ interface procedure resetfornewmodule; procedure collectglobalsyms; + procedure updatelocalvardbginfo(hp: taillvm; pd: tprocdef; functionscope: tai_llvmspecialisedmetadatanode); public constructor Create;override; destructor Destroy;override; @@ -330,6 +339,25 @@ implementation result:=taillvmdecl(entry^.Data); end; + + function TDebugInfoLLVM.localvarsym_get_meta(sym: tsym; out is_new: boolean): tai_llvmspecialisedmetadatanode; + var + entry: PHashSetItem; + begin + entry:=fstaticvarsymdecl.FindOrAdd(@sym,sizeof(sym)); + if not assigned(entry^.Data) then + begin + result:=tai_llvmspecialisedmetadatanode.create(tspecialisedmetadatanodekind.DILocalVariable); + current_asmdata.AsmLists[al_dwarf_info].concat(result); + entry^.Data:=result; + is_new:=true; + exit; + end; + is_new:=false; + result:=tai_llvmspecialisedmetadatanode(entry^.Data); + end; + + procedure TDebugInfoLLVM.appenddef_array_internal(list: TAsmList; fordef: tdef; eledef: tdef; lowrange, highrange: asizeint); var dinode, @@ -417,6 +445,7 @@ implementation fretainedtypes:=nil; fglobals:=nil; femptyexpression:=nil; + fderefexpression:=nil; fcunode:=nil; ffilemeta:=thashset.Create(10000,true,false); @@ -445,6 +474,8 @@ implementation fdefmeta:=nil; fstaticvarsymdecl.free; fstaticvarsymdecl:=nil; + flocalvarsymmeta.free; + flocalvarsymmeta:=nil; defnumberlist.free; defnumberlist:=nil; deftowritelist.free; @@ -473,12 +504,16 @@ implementation procedure TDebugInfoLLVM.ensuremetainit; begin + if not assigned(fllvm_dbg_addr_pd) then + fllvm_dbg_addr_pd:=search_system_proc('llvm_dbg_addr'); if not assigned(fenums) then begin fenums:=tai_llvmunnamedmetadatanode.create; fretainedtypes:=tai_llvmunnamedmetadatanode.create; fglobals:=tai_llvmunnamedmetadatanode.create; femptyexpression:=tai_llvmspecialisedmetadatanode.create(tspecialisedmetadatanodekind.DIExpression); + fderefexpression:=tai_llvmspecialisedmetadatanode.create(tspecialisedmetadatanodekind.DIExpression); + fderefexpression.addenum('','DW_OP_deref'); fcunode:=tai_llvmspecialisedmetadatanode.create(tspecialisedmetadatanodekind.DICompileUnit); end; end; @@ -515,6 +550,7 @@ implementation fretainedtypes:=nil; fglobals:=nil; femptyexpression:=nil; + fderefexpression:=nil; end; procedure TDebugInfoLLVM.collectglobalsyms; @@ -537,6 +573,60 @@ implementation end; end; + + procedure TDebugInfoLLVM.updatelocalvardbginfo(hp: taillvm; pd: tprocdef; functionscope: tai_llvmspecialisedmetadatanode); + var + opindex, callparaindex: longint; + paras: tfplist; + sympara, + exprpara: pllvmcallpara; + sym: tabstractnormalvarsym; + dilocalvar: tai_llvmspecialisedmetadatanode; + isnewlocalvardi, + deref: boolean; + begin + { not really clean since hardcoding the structure of the call + instruction's procdef encoding, but quick } + if (hp.oper[taillvm.callpdopernr]^.def.typ<>pointerdef) or + (tpointerdef(hp.oper[taillvm.callpdopernr]^.def).pointeddef<>fllvm_dbg_addr_pd) then + exit; + deref:=false; + + sympara:=hp.getcallpara(1); + exprpara:=hp.getcallpara(2); + + if sympara^.val.typ<>top_local then + internalerror(2022052613); + sym:=tabstractnormalvarsym(sympara^.val.localsym); + dilocalvar:=localvarsym_get_meta(sym,isnewlocalvardi); + sympara^.loadtai(llvm_getmetadatareftypedconst(dilocalvar)); + if isnewlocalvardi then + begin + dilocalvar.addstring('name',symname(sym,false)); + if sym.typ=paravarsym then + begin + dilocalvar.addint64('arg',tparavarsym(sym).paranr); + if paramanager.push_addr_param(sym.varspez,sym.vardef,pd.proccalloption) then + deref:=true; + end; + dilocalvar.addmetadatarefto('scope',functionscope); + try_add_file_metaref(dilocalvar,sym.fileinfo,false); + dilocalvar.addmetadatarefto('type',def_meta_node(sym.vardef)); + end + else + begin + if (sym.typ=paravarsym) and + paramanager.push_addr_param(sym.varspez,sym.vardef,pd.proccalloption) then + deref:=true; + end; + + if not deref then + exprpara^.loadtai(llvm_getmetadatareftypedconst(femptyexpression)) + else + exprpara^.loadtai(llvm_getmetadatareftypedconst(fderefexpression)); + end; + + function TDebugInfoLLVM.file_getmetanode(moduleindex: tfileposmoduleindex; fileindex: tfileposfileindex): tai_llvmspecialisedmetadatanode; var infile: tinputfile; @@ -2340,6 +2430,8 @@ implementation fglobals:=nil; current_asmdata.AsmLists[al_dwarf_info].Concat(femptyexpression); femptyexpression:=nil; + current_asmdata.AsmLists[al_dwarf_info].Concat(fderefexpression); + fderefexpression:=nil; if target_info.system in systems_darwin then fcunode.addenum('nameTableKind','GNU'); @@ -2476,6 +2568,7 @@ implementation hp: tai; functionscope, positionmeta: tai_llvmspecialisedmetadatanode; + pd: tprocdef; procdeffileinfo: tfileposinfo; nolineinfolevel : longint; firstline: boolean; @@ -2490,12 +2583,16 @@ implementation end; if not assigned(hp) then exit; - procdeffileinfo:=tprocdef(taillvmdecl(hp).def).fileinfo; + pd:=tprocdef(taillvmdecl(hp).def); + procdeffileinfo:=pd.fileinfo; { might trigger for certain kinds of internally generated code } if procdeffileinfo.fileindex=0 then exit; - functionscope:=def_meta_node(taillvmdecl(hp).def); + flocalvarsymmeta.free; + flocalvarsymmeta:=THashSet.Create((pd.localst.SymList.count+pd.parast.SymList.count)*4+1,true,false); + + functionscope:=def_meta_node(pd); nolineinfolevel:=0; hp:=tai(hp.next); @@ -2542,6 +2639,9 @@ implementation end; if assigned(positionmeta) then taillvm(hp).addinsmetadata(tai_llvmmetadatareferenceoperand.createreferenceto('dbg',positionmeta)); + if (cs_debuginfo in current_settings.moduleswitches) and + (taillvm(hp).llvmopcode=la_call) then + updatelocalvardbginfo(taillvm(hp),pd,functionscope); end; hp:=tai(hp.next); end; diff --git a/rtl/inc/llvmintr.inc b/rtl/inc/llvmintr.inc index 6e7063629c..e80933a46c 100644 --- a/rtl/inc/llvmintr.inc +++ b/rtl/inc/llvmintr.inc @@ -116,3 +116,5 @@ function llvm_experimental_constrained_uitofp_f64_i64(val: qword; rounding, exce {$ifdef SUPPORT_EXTENDED} function llvm_experimental_constrained_uitofp_f80_i64(val: qword; rounding, exceptions: LLVMMetadata): extended; compilerproc; external name 'llvm.experimental.constrained.uitofp.x86_fp80.i64'; {$endif} + +procedure llvm_dbg_addr(address, description, expression: LLVMMetadata); compilerproc; external name 'llvm.dbg.addr';