浏览代码

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.
Jonas Maebe 3 年之前
父节点
当前提交
25e832940c
共有 3 个文件被更改,包括 134 次插入8 次删除
  1. 29 5
      compiler/llvm/aasmllvm.pas
  2. 103 3
      compiler/llvm/dbgllvm.pas
  3. 2 0
      rtl/inc/llvmintr.inc

+ 29 - 5
compiler/llvm/aasmllvm.pas

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

+ 103 - 3
compiler/llvm/dbgllvm.pas

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

+ 2 - 0
rtl/inc/llvmintr.inc

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