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.
This commit is contained in:
Jonas Maebe 2022-06-04 22:14:02 +02:00
parent e7ec91eca8
commit 25e832940c
3 changed files with 134 additions and 8 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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';