Pārlūkot izejas kodu

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 gadi atpakaļ
vecāks
revīzija
25e832940c
3 mainītis faili ar 134 papildinājumiem un 8 dzēšanām
  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;
 
     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);

+ 103 - 3
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;

+ 2 - 0
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';