mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-13 09:39:09 +02:00
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:
parent
e7ec91eca8
commit
25e832940c
@ -33,8 +33,13 @@ interface
|
|||||||
llvmbase;
|
llvmbase;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
pllvmcallpara = ^tllvmcallpara;
|
||||||
|
|
||||||
{ taillvm }
|
{ taillvm }
|
||||||
taillvm = class(tai_cpu_abstract_sym)
|
taillvm = class(tai_cpu_abstract_sym)
|
||||||
|
const
|
||||||
|
callpdopernr = 3;
|
||||||
|
var
|
||||||
llvmopcode: tllvmop;
|
llvmopcode: tllvmop;
|
||||||
metadata: tai;
|
metadata: tai;
|
||||||
|
|
||||||
@ -145,6 +150,8 @@ interface
|
|||||||
procedure loadasmlist(opidx: longint; _asmlist: tasmlist);
|
procedure loadasmlist(opidx: longint; _asmlist: tasmlist);
|
||||||
procedure loadcallingconvention(opidx: longint; calloption: tproccalloption);
|
procedure loadcallingconvention(opidx: longint; calloption: tproccalloption);
|
||||||
|
|
||||||
|
function getcallpara(callparaindex: longint): pllvmcallpara;
|
||||||
|
|
||||||
procedure addinsmetadata(insmeta: tai);
|
procedure addinsmetadata(insmeta: tai);
|
||||||
|
|
||||||
procedure landingpad_add_clause(op: tllvmop; def: tdef; kind: TAsmSymbol);
|
procedure landingpad_add_clause(op: tllvmop; def: tdef; kind: TAsmSymbol);
|
||||||
@ -220,10 +227,10 @@ interface
|
|||||||
top_const: (value: int64);
|
top_const: (value: int64);
|
||||||
top_undef : ();
|
top_undef : ();
|
||||||
top_tai : (ai: tai);
|
top_tai : (ai: tai);
|
||||||
|
top_local : (localsym: tsym);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ parameter to an llvm call instruction }
|
{ parameter to an llvm call instruction }
|
||||||
pllvmcallpara = ^tllvmcallpara;
|
|
||||||
tllvmcallpara = object
|
tllvmcallpara = object
|
||||||
def: tdef;
|
def: tdef;
|
||||||
alignment: shortint;
|
alignment: shortint;
|
||||||
@ -560,6 +567,23 @@ implementation
|
|||||||
end;
|
end;
|
||||||
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);
|
procedure taillvm.addinsmetadata(insmeta: tai);
|
||||||
begin
|
begin
|
||||||
insmeta.next:=metadata;
|
insmeta.next:=metadata;
|
||||||
@ -1204,7 +1228,7 @@ implementation
|
|||||||
loaddef(0,retsize);
|
loaddef(0,retsize);
|
||||||
loadreg(1,dst);
|
loadreg(1,dst);
|
||||||
loadcallingconvention(2,cc);
|
loadcallingconvention(2,cc);
|
||||||
loaddef(3,callpd);
|
loaddef(callpdopernr,callpd);
|
||||||
loadsymbol(4,name,0);
|
loadsymbol(4,name,0);
|
||||||
loadparas(5,paras);
|
loadparas(5,paras);
|
||||||
end;
|
end;
|
||||||
@ -1217,7 +1241,7 @@ implementation
|
|||||||
loaddef(0,retsize);
|
loaddef(0,retsize);
|
||||||
loadreg(1,dst);
|
loadreg(1,dst);
|
||||||
loadcallingconvention(2,cc);
|
loadcallingconvention(2,cc);
|
||||||
loaddef(3,callpd);
|
loaddef(callpdopernr,callpd);
|
||||||
loadreg(4,reg);
|
loadreg(4,reg);
|
||||||
loadparas(5,paras);
|
loadparas(5,paras);
|
||||||
end;
|
end;
|
||||||
@ -1230,7 +1254,7 @@ implementation
|
|||||||
loaddef(0,retsize);
|
loaddef(0,retsize);
|
||||||
loadreg(1,dst);
|
loadreg(1,dst);
|
||||||
loadcallingconvention(2,cc);
|
loadcallingconvention(2,cc);
|
||||||
loaddef(3,callpd);
|
loaddef(callpdopernr,callpd);
|
||||||
loadsymbol(4,name,0);
|
loadsymbol(4,name,0);
|
||||||
loadparas(5,paras);
|
loadparas(5,paras);
|
||||||
loadsymbol(6,retlab,0);
|
loadsymbol(6,retlab,0);
|
||||||
@ -1245,7 +1269,7 @@ implementation
|
|||||||
loaddef(0,retsize);
|
loaddef(0,retsize);
|
||||||
loadreg(1,dst);
|
loadreg(1,dst);
|
||||||
loadcallingconvention(2,cc);
|
loadcallingconvention(2,cc);
|
||||||
loaddef(3,callpd);
|
loaddef(callpdopernr,callpd);
|
||||||
loadreg(4,reg);
|
loadreg(4,reg);
|
||||||
loadparas(5,paras);
|
loadparas(5,paras);
|
||||||
loadsymbol(6,retlab,0);
|
loadsymbol(6,retlab,0);
|
||||||
|
@ -77,13 +77,19 @@ interface
|
|||||||
flexicalblockfilemeta: THashSet;
|
flexicalblockfilemeta: THashSet;
|
||||||
{ lookup table for tstaticvarsym -> taillvmdecl }
|
{ lookup table for tstaticvarsym -> taillvmdecl }
|
||||||
fstaticvarsymdecl: THashSet;
|
fstaticvarsymdecl: THashSet;
|
||||||
|
{ lookup table for local/paravarsym -> metadata }
|
||||||
|
flocalvarsymmeta: THashSet;
|
||||||
|
|
||||||
fcunode: tai_llvmspecialisedmetadatanode;
|
fcunode: tai_llvmspecialisedmetadatanode;
|
||||||
fenums: tai_llvmunnamedmetadatanode;
|
fenums: tai_llvmunnamedmetadatanode;
|
||||||
fretainedtypes: tai_llvmunnamedmetadatanode;
|
fretainedtypes: tai_llvmunnamedmetadatanode;
|
||||||
fglobals: tai_llvmunnamedmetadatanode;
|
fglobals: tai_llvmunnamedmetadatanode;
|
||||||
{ reusable empty expression node }
|
{ 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;
|
function absolute_llvm_path(const s:tcmdstr):tcmdstr;
|
||||||
protected
|
protected
|
||||||
@ -104,6 +110,8 @@ interface
|
|||||||
procedure staticvarsym_set_decl(sym: tsym; decl: taillvmdecl);
|
procedure staticvarsym_set_decl(sym: tsym; decl: taillvmdecl);
|
||||||
function staticvarsym_get_decl(sym: tsym): 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);
|
procedure appenddef_array_internal(list: TAsmList; fordef: tdef; eledef: tdef; lowrange, highrange: asizeint);
|
||||||
function getabstractprocdeftypes(list: TAsmList; def:tabstractprocdef): tai_llvmbasemetadatanode;
|
function getabstractprocdeftypes(list: TAsmList; def:tabstractprocdef): tai_llvmbasemetadatanode;
|
||||||
|
|
||||||
@ -157,6 +165,7 @@ interface
|
|||||||
procedure resetfornewmodule;
|
procedure resetfornewmodule;
|
||||||
|
|
||||||
procedure collectglobalsyms;
|
procedure collectglobalsyms;
|
||||||
|
procedure updatelocalvardbginfo(hp: taillvm; pd: tprocdef; functionscope: tai_llvmspecialisedmetadatanode);
|
||||||
public
|
public
|
||||||
constructor Create;override;
|
constructor Create;override;
|
||||||
destructor Destroy;override;
|
destructor Destroy;override;
|
||||||
@ -330,6 +339,25 @@ implementation
|
|||||||
result:=taillvmdecl(entry^.Data);
|
result:=taillvmdecl(entry^.Data);
|
||||||
end;
|
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);
|
procedure TDebugInfoLLVM.appenddef_array_internal(list: TAsmList; fordef: tdef; eledef: tdef; lowrange, highrange: asizeint);
|
||||||
var
|
var
|
||||||
dinode,
|
dinode,
|
||||||
@ -417,6 +445,7 @@ implementation
|
|||||||
fretainedtypes:=nil;
|
fretainedtypes:=nil;
|
||||||
fglobals:=nil;
|
fglobals:=nil;
|
||||||
femptyexpression:=nil;
|
femptyexpression:=nil;
|
||||||
|
fderefexpression:=nil;
|
||||||
fcunode:=nil;
|
fcunode:=nil;
|
||||||
|
|
||||||
ffilemeta:=thashset.Create(10000,true,false);
|
ffilemeta:=thashset.Create(10000,true,false);
|
||||||
@ -445,6 +474,8 @@ implementation
|
|||||||
fdefmeta:=nil;
|
fdefmeta:=nil;
|
||||||
fstaticvarsymdecl.free;
|
fstaticvarsymdecl.free;
|
||||||
fstaticvarsymdecl:=nil;
|
fstaticvarsymdecl:=nil;
|
||||||
|
flocalvarsymmeta.free;
|
||||||
|
flocalvarsymmeta:=nil;
|
||||||
defnumberlist.free;
|
defnumberlist.free;
|
||||||
defnumberlist:=nil;
|
defnumberlist:=nil;
|
||||||
deftowritelist.free;
|
deftowritelist.free;
|
||||||
@ -473,12 +504,16 @@ implementation
|
|||||||
|
|
||||||
procedure TDebugInfoLLVM.ensuremetainit;
|
procedure TDebugInfoLLVM.ensuremetainit;
|
||||||
begin
|
begin
|
||||||
|
if not assigned(fllvm_dbg_addr_pd) then
|
||||||
|
fllvm_dbg_addr_pd:=search_system_proc('llvm_dbg_addr');
|
||||||
if not assigned(fenums) then
|
if not assigned(fenums) then
|
||||||
begin
|
begin
|
||||||
fenums:=tai_llvmunnamedmetadatanode.create;
|
fenums:=tai_llvmunnamedmetadatanode.create;
|
||||||
fretainedtypes:=tai_llvmunnamedmetadatanode.create;
|
fretainedtypes:=tai_llvmunnamedmetadatanode.create;
|
||||||
fglobals:=tai_llvmunnamedmetadatanode.create;
|
fglobals:=tai_llvmunnamedmetadatanode.create;
|
||||||
femptyexpression:=tai_llvmspecialisedmetadatanode.create(tspecialisedmetadatanodekind.DIExpression);
|
femptyexpression:=tai_llvmspecialisedmetadatanode.create(tspecialisedmetadatanodekind.DIExpression);
|
||||||
|
fderefexpression:=tai_llvmspecialisedmetadatanode.create(tspecialisedmetadatanodekind.DIExpression);
|
||||||
|
fderefexpression.addenum('','DW_OP_deref');
|
||||||
fcunode:=tai_llvmspecialisedmetadatanode.create(tspecialisedmetadatanodekind.DICompileUnit);
|
fcunode:=tai_llvmspecialisedmetadatanode.create(tspecialisedmetadatanodekind.DICompileUnit);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -515,6 +550,7 @@ implementation
|
|||||||
fretainedtypes:=nil;
|
fretainedtypes:=nil;
|
||||||
fglobals:=nil;
|
fglobals:=nil;
|
||||||
femptyexpression:=nil;
|
femptyexpression:=nil;
|
||||||
|
fderefexpression:=nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TDebugInfoLLVM.collectglobalsyms;
|
procedure TDebugInfoLLVM.collectglobalsyms;
|
||||||
@ -537,6 +573,60 @@ implementation
|
|||||||
end;
|
end;
|
||||||
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;
|
function TDebugInfoLLVM.file_getmetanode(moduleindex: tfileposmoduleindex; fileindex: tfileposfileindex): tai_llvmspecialisedmetadatanode;
|
||||||
var
|
var
|
||||||
infile: tinputfile;
|
infile: tinputfile;
|
||||||
@ -2340,6 +2430,8 @@ implementation
|
|||||||
fglobals:=nil;
|
fglobals:=nil;
|
||||||
current_asmdata.AsmLists[al_dwarf_info].Concat(femptyexpression);
|
current_asmdata.AsmLists[al_dwarf_info].Concat(femptyexpression);
|
||||||
femptyexpression:=nil;
|
femptyexpression:=nil;
|
||||||
|
current_asmdata.AsmLists[al_dwarf_info].Concat(fderefexpression);
|
||||||
|
fderefexpression:=nil;
|
||||||
|
|
||||||
if target_info.system in systems_darwin then
|
if target_info.system in systems_darwin then
|
||||||
fcunode.addenum('nameTableKind','GNU');
|
fcunode.addenum('nameTableKind','GNU');
|
||||||
@ -2476,6 +2568,7 @@ implementation
|
|||||||
hp: tai;
|
hp: tai;
|
||||||
functionscope,
|
functionscope,
|
||||||
positionmeta: tai_llvmspecialisedmetadatanode;
|
positionmeta: tai_llvmspecialisedmetadatanode;
|
||||||
|
pd: tprocdef;
|
||||||
procdeffileinfo: tfileposinfo;
|
procdeffileinfo: tfileposinfo;
|
||||||
nolineinfolevel : longint;
|
nolineinfolevel : longint;
|
||||||
firstline: boolean;
|
firstline: boolean;
|
||||||
@ -2490,12 +2583,16 @@ implementation
|
|||||||
end;
|
end;
|
||||||
if not assigned(hp) then
|
if not assigned(hp) then
|
||||||
exit;
|
exit;
|
||||||
procdeffileinfo:=tprocdef(taillvmdecl(hp).def).fileinfo;
|
pd:=tprocdef(taillvmdecl(hp).def);
|
||||||
|
procdeffileinfo:=pd.fileinfo;
|
||||||
{ might trigger for certain kinds of internally generated code }
|
{ might trigger for certain kinds of internally generated code }
|
||||||
if procdeffileinfo.fileindex=0 then
|
if procdeffileinfo.fileindex=0 then
|
||||||
exit;
|
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;
|
nolineinfolevel:=0;
|
||||||
hp:=tai(hp.next);
|
hp:=tai(hp.next);
|
||||||
@ -2542,6 +2639,9 @@ implementation
|
|||||||
end;
|
end;
|
||||||
if assigned(positionmeta) then
|
if assigned(positionmeta) then
|
||||||
taillvm(hp).addinsmetadata(tai_llvmmetadatareferenceoperand.createreferenceto('dbg',positionmeta));
|
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;
|
end;
|
||||||
hp:=tai(hp.next);
|
hp:=tai(hp.next);
|
||||||
end;
|
end;
|
||||||
|
@ -116,3 +116,5 @@ function llvm_experimental_constrained_uitofp_f64_i64(val: qword; rounding, exce
|
|||||||
{$ifdef SUPPORT_EXTENDED}
|
{$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';
|
function llvm_experimental_constrained_uitofp_f80_i64(val: qword; rounding, exceptions: LLVMMetadata): extended; compilerproc; external name 'llvm.experimental.constrained.uitofp.x86_fp80.i64';
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
|
procedure llvm_dbg_addr(address, description, expression: LLVMMetadata); compilerproc; external name 'llvm.dbg.addr';
|
||||||
|
Loading…
Reference in New Issue
Block a user