123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378 |
- {
- Copyright (c) 2008,2015 by Peter Vreman, Florian Klaempfl and Jonas Maebe
- This units contains support for generating LLVM type info
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- ****************************************************************************
- }
- {
- This units contains support for LLVM type info generation.
- It's based on the debug info system, since it's quite similar
- }
- unit llvmtype;
- {$i fpcdefs.inc}
- {$h+}
- interface
- uses
- cclasses,globtype,
- aasmbase,aasmtai,aasmdata,
- symbase,symtype,symdef,symsym,
- finput,
- dbgbase;
- { TLLVMTypeInfo }
- type
- TLLVMTypeInfo = class(TDebugInfo)
- protected
- function record_def(def:tdef): tdef;
- procedure appenddef_array(list:TAsmList;def:tarraydef);override;
- procedure appenddef_abstractrecord(list:TAsmList;def:tabstractrecorddef);
- procedure appenddef_record(list:TAsmList;def:trecorddef);override;
- procedure appenddef_pointer(list:TAsmList;def:tpointerdef);override;
- procedure appenddef_procvar(list:TAsmList;def:tprocvardef);override;
- procedure appendprocdef(list:TAsmList;def:tprocdef);override;
- procedure appenddef_object(list:TAsmList;def: tobjectdef);override;
- procedure appenddef_variant(list:TAsmList;def: tvariantdef);override;
- procedure appendsym_var(list:TAsmList;sym:tabstractnormalvarsym);
- procedure appendsym_staticvar(list:TAsmList;sym:tstaticvarsym);override;
- procedure appendsym_paravar(list:TAsmList;sym:tparavarsym);override;
- procedure appendsym_localvar(list:TAsmList;sym:tlocalvarsym);override;
- procedure appendsym_fieldvar(list:TAsmList;sym:tfieldvarsym);override;
- procedure appendsym_const(list:TAsmList;sym:tconstsym);override;
- procedure appendsym_absolute(list:TAsmList;sym:tabsolutevarsym);override;
- procedure enum_membersyms_callback(p:TObject;arg:pointer);
- procedure process_llvmins(deftypelist: tasmlist; p: tai);
- procedure process_tai(deftypelist: tasmlist; p: tai);
- procedure process_asmlist(deftypelist, asmlist: tasmlist);
- public
- constructor Create;override;
- destructor Destroy;override;
- procedure inserttypeinfo;override;
- end;
- implementation
- uses
- sysutils,cutils,cfileutl,constexp,
- version,globals,verbose,systems,
- cpubase,cgbase,paramgr,
- fmodule,nobj,
- defutil,symconst,symtable,
- llvmbase, aasmllvm, aasmcnst;
- {****************************************************************************
- TDebugInfoDwarf
- ****************************************************************************}
- function TLLVMTypeInfo.record_def(def:tdef): tdef;
- begin
- result:=def;
- if def.dbg_state<>dbg_state_unused then
- exit;
- def.dbg_state:=dbg_state_used;
- deftowritelist.Add(def);
- defnumberlist.Add(def);
- end;
- constructor TLLVMTypeInfo.Create;
- begin
- inherited Create;
- end;
- destructor TLLVMTypeInfo.Destroy;
- begin
- inherited destroy;
- end;
- procedure TLLVMTypeInfo.enum_membersyms_callback(p:TObject; arg: pointer);
- begin
- case tsym(p).typ of
- fieldvarsym:
- appendsym_fieldvar(TAsmList(arg),tfieldvarsym(p));
- end;
- end;
- procedure TLLVMTypeInfo.process_llvmins(deftypelist: tasmlist; p: tai);
- var
- opidx, paraidx: longint;
- callpara: pllvmcallpara;
- begin
- for opidx:=0 to taillvm(p).ops-1 do
- case taillvm(p).oper[opidx]^.typ of
- top_def:
- appenddef(deftypelist,taillvm(p).oper[opidx]^.def);
- top_tai:
- process_tai(deftypelist,taillvm(p).oper[opidx]^.ai);
- top_para:
- for paraidx:=0 to taillvm(p).oper[opidx]^.paras.count-1 do
- begin
- callpara:=pllvmcallpara(taillvm(p).oper[opidx]^.paras[paraidx]);
- appenddef(deftypelist,callpara^.def);
- end;
- end;
- end;
- procedure TLLVMTypeInfo.process_tai(deftypelist: tasmlist; p: tai);
- begin
- case p.typ of
- ait_llvmalias:
- appenddef(deftypelist,taillvmalias(p).def);
- ait_llvmdecl:
- appenddef(deftypelist,taillvmdecl(p).def);
- ait_llvmins:
- process_llvmins(deftypelist,p);
- ait_typedconst:
- appenddef(deftypelist,tai_abstracttypedconst(p).def);
- end;
- end;
- procedure TLLVMTypeInfo.process_asmlist(deftypelist, asmlist: tasmlist);
- var
- hp: tai;
- begin
- if not assigned(asmlist) then
- exit;
- hp:=tai(asmlist.first);
- while assigned(hp) do
- begin
- process_tai(deftypelist,hp);
- hp:=tai(hp.next);
- end;
- end;
- procedure TLLVMTypeInfo.appenddef_array(list:TAsmList;def:tarraydef);
- begin
- appenddef(list,def.elementdef);
- end;
- procedure TLLVMTypeInfo.appenddef_abstractrecord(list:TAsmList;def:tabstractrecorddef);
- var
- symdeflist: tfpobjectlist;
- i: longint;
- begin
- symdeflist:=tabstractrecordsymtable(def.symtable).llvmst.symdeflist;
- for i:=0 to symdeflist.Count-1 do
- appenddef(list,tllvmshadowsymtableentry(symdeflist[i]).def);
- if assigned(def.typesym) then
- list.concat(taillvm.op_size(LA_TYPE,record_def(def)));
- end;
- procedure TLLVMTypeInfo.appenddef_record(list:TAsmList;def:trecorddef);
- begin
- appenddef_abstractrecord(list,def);
- end;
- procedure TLLVMTypeInfo.appenddef_pointer(list:TAsmList;def:tpointerdef);
- begin
- appenddef(list,def.pointeddef);
- end;
- procedure TLLVMTypeInfo.appenddef_procvar(list:TAsmList;def:tprocvardef);
- var
- i: longint;
- begin
- { todo: handle mantis #25551; there is no way to create a symbolic
- la_type for a procvardef (unless it's a procedure of object/record),
- which means that recursive references should become plain "procedure"
- types that are then casted to the real type when they are used }
- for i:=0 to def.paras.count-1 do
- appenddef(list,tparavarsym(def.paras[i]).vardef);
- appenddef(list,def.returndef);
- if assigned(def.typesym) and
- not def.is_addressonly then
- list.concat(taillvm.op_size(LA_TYPE,record_def(def)));
- end;
- procedure TLLVMTypeInfo.appendprocdef(list:TAsmList;def:tprocdef);
- begin
- { the procdef itself is already written by appendprocdef_implicit }
-
- { last write the types from this procdef }
- if assigned(def.parast) then
- write_symtable_defs(current_asmdata.asmlists[al_start],def.parast);
- if assigned(def.localst) and
- (def.localst.symtabletype=localsymtable) then
- write_symtable_defs(current_asmdata.asmlists[al_start],def.localst);
- end;
- procedure TLLVMTypeInfo.appendsym_var(list:TAsmList;sym:tabstractnormalvarsym);
- begin
- appenddef(list,sym.vardef);
- end;
- procedure TLLVMTypeInfo.appendsym_staticvar(list:TAsmList;sym:tstaticvarsym);
- begin
- appendsym_var(list,sym);
- end;
- procedure TLLVMTypeInfo.appendsym_localvar(list:TAsmList;sym:tlocalvarsym);
- begin
- appendsym_var(list,sym);
- end;
- procedure TLLVMTypeInfo.appendsym_paravar(list:TAsmList;sym:tparavarsym);
- begin
- appendsym_var(list,sym);
- end;
- procedure TLLVMTypeInfo.appendsym_fieldvar(list:TAsmList;sym: tfieldvarsym);
- begin
- appenddef(list,sym.vardef);
- end;
- procedure TLLVMTypeInfo.appendsym_const(list:TAsmList;sym:tconstsym);
- begin
- appenddef(list,sym.constdef);
- end;
- procedure TLLVMTypeInfo.appendsym_absolute(list:TAsmList;sym:tabsolutevarsym);
- begin
- appenddef(list,sym.vardef);
- end;
- procedure TLLVMTypeInfo.inserttypeinfo;
- procedure write_defs_to_write;
- var
- n : integer;
- looplist,
- templist: TFPObjectList;
- def : tdef;
- begin
- templist := TFPObjectList.Create(False);
- looplist := deftowritelist;
- while looplist.count > 0 do
- begin
- deftowritelist := templist;
- for n := 0 to looplist.count - 1 do
- begin
- def := tdef(looplist[n]);
- case def.dbg_state of
- dbg_state_written:
- continue;
- dbg_state_writing:
- internalerror(200610052);
- dbg_state_unused:
- internalerror(200610053);
- dbg_state_used:
- appenddef(current_asmdata.asmlists[al_start],def)
- else
- internalerror(200610054);
- end;
- end;
- looplist.clear;
- templist := looplist;
- looplist := deftowritelist;
- end;
- templist.free;
- end;
- var
- storefilepos: tfileposinfo;
- def: tdef;
- i: longint;
- hal: tasmlisttype;
- begin
- storefilepos:=current_filepos;
- current_filepos:=current_module.mainfilepos;
- defnumberlist:=TFPObjectList.create(false);
- deftowritelist:=TFPObjectList.create(false);
- { write all global/static variables, part of flaggin all required tdefs }
- if assigned(current_module.globalsymtable) then
- write_symtable_syms(current_asmdata.asmlists[al_start],current_module.globalsymtable);
- if assigned(current_module.localsymtable) then
- write_symtable_syms(current_asmdata.asmlists[al_start],current_module.localsymtable);
- { write all procedures and methods, part of flagging all required tdefs }
- if assigned(current_module.globalsymtable) then
- write_symtable_procdefs(current_asmdata.asmlists[al_start],current_module.globalsymtable);
- if assigned(current_module.localsymtable) then
- write_symtable_procdefs(current_asmdata.asmlists[al_start],current_module.localsymtable);
- { process all llvm instructions, part of flagging all required tdefs }
- for hal:=low(TasmlistType) to high(TasmlistType) do
- if hal<>al_start then
- process_asmlist(current_asmdata.asmlists[al_start],current_asmdata.asmlists[hal]);
- { write all used defs }
- write_defs_to_write;
- { reset all def labels }
- for i:=0 to defnumberlist.count-1 do
- begin
- def := tdef(defnumberlist[i]);
- if assigned(def) then
- begin
- def.dbg_state:=dbg_state_unused;
- end;
- end;
- defnumberlist.free;
- defnumberlist:=nil;
- deftowritelist.free;
- deftowritelist:=nil;
- current_filepos:=storefilepos;
- end;
- procedure TLLVMTypeInfo.appenddef_object(list:TAsmList;def: tobjectdef);
- begin
- appenddef_abstractrecord(list,def);
- end;
- procedure TLLVMTypeInfo.appenddef_variant(list:TAsmList;def: tvariantdef);
- begin
- appenddef(list,tabstractrecorddef(search_system_type('TVARDATA').typedef));
- end;
- end.
|