mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 21:28:03 +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;
|
||||
|
||||
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);
|
||||
|
@ -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;
|
||||
|
@ -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';
|
||||
|
Loading…
Reference in New Issue
Block a user