fpc/compiler/symtype.pas
Jonas Maebe 060d81b8fa Merged revisions 11878,11881-11882,11889,11891-11893,11895,11899-11902,11935,11938,12212,12304,12308-12310,12316,12330-12332,12334,12339-12340 via svnmerge from
svn+ssh://jonas@svn.freepascal.org/FPC/svn/fpc/branches/wpo

........
r11878 | jonas | 2008-10-11 02:25:18 +0200 (Sat, 11 Oct 2008) | 19 lines

  + initial implementation of whole-program optimisation framework
  + implementation of whole-program devirtualisation
  o use:
     a) generate whole-program optimisation information (no need
        to completely compile the program and all of its units
        with -OW/-FW, only the main program is sufficient)
      fpc -OWdevirtcalls -FWmyprog.wpo myprog
     b) use it to optimise the program
      fpc -B -Owdevirtcalls -Fwmyprog.wpo myprog
     (the -B is not required, but only sources recompiled during
      the second pass will actually be optimised -- if you want,
      you can even rebuild the rtl devirtualised for a particular 
      program; and these options can obviously also be used         
      together with regular optimisation switches)
  o warning:
    - there are no checks yet to ensure that you do not use 
      units optimised for a particular program with another
      program (or with a changed version of the same program)

........
r11881 | jonas | 2008-10-11 19:35:52 +0200 (Sat, 11 Oct 2008) | 13 lines

  * extracted code to detect constructed class/object types from
    tcallnode.gen_vmt_tree into its own method to avoid clutter
  * detect x.classtype.create constructs (with classtype = the
    system.tobject.classtype method), and treat them as if a
    "class of x" has been instantiated rather than a
    "class of tobject". this required storing the instantiated
    classrefs in their own array though, because at such a
    point we don't have a "class of x" tdef available (so
    now "x", and all other defs instantiated via a classref,
    are now stored as tobjectdefs in a separate array)
  + support for devirtualising class methods (including
    constructors)

........
r11882 | jonas | 2008-10-11 20:44:02 +0200 (Sat, 11 Oct 2008) | 7 lines

  + -Owoptvmts whole program optimisation which replaces vmt entries
    with method names of child classes in case the current class'
    method can never be called (e.g., because this class is never
    instantiated). As a result, such methods can then be removed
    by dead code removal/smart linking (not much effect for either
    the compiler, lazarus or a trivial lazarus app though).

........
r11889 | jonas | 2008-10-12 14:29:54 +0200 (Sun, 12 Oct 2008) | 2 lines

  * some comment fixes

........
r11891 | jonas | 2008-10-12 18:49:13 +0200 (Sun, 12 Oct 2008) | 4 lines

  * fixed twpofilereader.getnextnoncommentline() when reusing a previously
    read line
  * fixed skipping of unnecessary wpo feedback file sections

........
r11892 | jonas | 2008-10-12 23:42:43 +0200 (Sun, 12 Oct 2008) | 31 lines

  + symbol liveness wpo information extracted from smartlinked programs
    (-OW/-Owsymbolliveness)
  + use symbol liveness information to improve devirtualisation (don't
    consider classes created in code that has been dead code stripped).
    This requires at least two passes of using wpo (first uses dead code
    info to locate classes that are constructed only in dead code,
    second pass uses this info to potentially further devirtualise).
    I.e.:
     1) generate initial liveness and devirtualisation feedback
       fpc -FWtt.wpo -OWall tt.pp -Xs- -CX -XX
     2) use previously generated feedback, and regenerate new feedback
        based on this (i.e., disregard classes created in dead code)
       fpc -FWtt-1.wpo -OWall -Fwtt.wo -Owall tt.pp -Xs- -CX -XX
     3) use the newly generated feedback (in theory, it is possible
        that even more opportunities pop up afterwards; you can
        continue until the program does not get smaller anymore)
       fpc -Fwtt-1.wpo -Owall tt.pp -CX -XX
  * changed all message() to cgmessage() calls so the set codegenerror
  * changed static fsectionhandlers field to a regular field called
    fwpocomponents
  * changed registration of wpocomponents: no longer happens in the
    initialization section of their unit, but in the InitWpo routine
    (which has been moved from the woinfo to the wpo unit). This way
    you can register different classes based on the target/parameters.
  + added static method to twpocomponentbase for checking whether
    the command line parameters don't conflict with the requested
    optimisations (e.g. generating liveness info requires that
    smartlinking is turned on)
  + added static method to twpocomponentbase to request the
    section name

........
r11893 | jonas | 2008-10-12 23:53:57 +0200 (Sun, 12 Oct 2008) | 3 lines

  * fixed comment error (twpodeadcodeinfo keeps a list of live,
    not dead symbols)

........
r11895 | jonas | 2008-10-13 00:13:59 +0200 (Mon, 13 Oct 2008) | 2 lines

  + documented -OW<x>, -Ow<x>, -FW<x> and -Fw<x> wpo parameters

........
r11899 | jonas | 2008-10-14 22:14:56 +0200 (Tue, 14 Oct 2008) | 2 lines

  * replaced hardcoded string with objdumpsearchstr constant

........
r11900 | jonas | 2008-10-14 22:15:25 +0200 (Tue, 14 Oct 2008) | 2 lines

  * reset wpofeedbackinput and wpofeedbackoutput in wpodone

........
r11901 | jonas | 2008-10-14 22:16:07 +0200 (Tue, 14 Oct 2008) | 2 lines

  * various additional comments and comment fixes

........
r11902 | jonas | 2008-10-15 18:09:42 +0200 (Wed, 15 Oct 2008) | 5 lines

  * store vmt procdefs in the ppu files so we don't have to use a hack to
    regenerate them for whole-program optimisation
  * fixed crash when performing devirtualisation optimisation on programs
    that do not construct any classes/objects with optimisable vmts

........
r11935 | jonas | 2008-10-19 12:24:26 +0200 (Sun, 19 Oct 2008) | 4 lines

  * set the vmt entries of non-class virtual methods of not instantiated
    objects/classes to FPC_ABSTRACTERROR so the code they refer to can
    be thrown away if it is not referred to in any other way either

........
r11938 | jonas | 2008-10-19 20:55:02 +0200 (Sun, 19 Oct 2008) | 7 lines

  * record all classrefdefs/objdefs for which a loadvmtaddrnode is generated,
    and instead of marking all classes that derive from instantiated
    classrefdefs as instantiated, only mark those classes from the above
    collection that derive from instantiated classrefdefs as
    instantiated (since to instantiate a class, you have to load its vmt
    somehow -- this may be broken by using assembler code though)

........
r12212 | jonas | 2008-11-23 12:26:34 +0100 (Sun, 23 Nov 2008) | 3 lines

  * fixed to work with the new vmtentries that are always available and
    removed previously added code to save/load vmtentries to ppu files

........
r12304 | jonas | 2008-12-05 22:23:30 +0100 (Fri, 05 Dec 2008) | 4 lines

  * check whether the correct wpo feedback file is used in the current
    compilation when using units that were compiled using wpo information
    during a previous compilation run

........
r12308 | jonas | 2008-12-06 18:03:39 +0100 (Sat, 06 Dec 2008) | 2 lines

  * abort compilation if an error occurred during wpo initialisation

........
r12309 | jonas | 2008-12-06 18:04:28 +0100 (Sat, 06 Dec 2008) | 3 lines

  * give an error message instead of crashing with an io exception if the
    compiler is unable to create the wpo feedback file specified using -FW

........
r12310 | jonas | 2008-12-06 18:12:43 +0100 (Sat, 06 Dec 2008) | 3 lines

  * don't let the used wpo feedback file influence the interface crc (there's
    a separate check for such changes)

........
r12316 | jonas | 2008-12-08 19:08:25 +0100 (Mon, 08 Dec 2008) | 3 lines

  * document the format of the sections of the wpo feedback file inside the
    feedback file itself

........
r12330 | jonas | 2008-12-10 22:26:47 +0100 (Wed, 10 Dec 2008) | 2 lines

  * use sysutils instead of dos to avoid command line length limits

........
r12331 | jonas | 2008-12-10 22:31:11 +0100 (Wed, 10 Dec 2008) | 3 lines

  + support for testing whole program optimisation tests (multiple
    compilations using successively generated feedback files)

........
r12332 | jonas | 2008-12-10 22:31:40 +0100 (Wed, 10 Dec 2008) | 2 lines

  + whole program optimisation tests

........
r12334 | jonas | 2008-12-10 22:38:07 +0100 (Wed, 10 Dec 2008) | 2 lines

  - removed unused local variable

........
r12339 | jonas | 2008-12-11 18:06:36 +0100 (Thu, 11 Dec 2008) | 2 lines

  + comments for newly added fields to tobjectdef for devirtualisation

........
r12340 | jonas | 2008-12-11 18:10:01 +0100 (Thu, 11 Dec 2008) | 2 lines

  * increase ppu version (was no longer different from trunk due to merging)

........

git-svn-id: trunk@12341 -
2008-12-11 17:40:18 +00:00

1010 lines
26 KiB
ObjectPascal

{
Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
This unit handles the symbol tables
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.
****************************************************************************
}
unit symtype;
{$i fpcdefs.inc}
interface
uses
{ common }
cutils,
cclasses,
{ global }
globtype,globals,constexp,
{ symtable }
symconst,symbase,
{ aasm }
aasmbase,ppu,cpuinfo
;
type
{************************************************
Required Forwards
************************************************}
tsym = class;
Tcompilerppufile=class;
{************************************************
TDef
************************************************}
tgeTSymtable = (gs_none,gs_record,gs_local,gs_para);
tdef = class(TDefEntry)
typesym : tsym; { which type the definition was generated this def }
{ maybe it's useful to merge the dwarf and stabs debugging info with some hacking }
{ dwarf debugging }
dwarf_lab : tasmsymbol;
dwarf_ref_lab : tasmsymbol;
{ stabs debugging }
stab_number : word;
dbg_state : tdefdbgstatus;
defoptions : tdefoptions;
defstates : tdefstates;
constructor create(dt:tdeftyp);
procedure buildderef;virtual;abstract;
procedure buildderefimpl;virtual;abstract;
procedure deref;virtual;abstract;
procedure derefimpl;virtual;abstract;
function typename:string;
function GetTypeName:string;virtual;
function mangledparaname:string;
function getmangledparaname:string;virtual;
function rtti_mangledname(rt:trttitype):string;virtual;abstract;
function size:aint;virtual;abstract;
function packedbitsize:aint;virtual;
function alignment:shortint;virtual;abstract;
function getvardef:longint;virtual;abstract;
function getparentdef:tdef;virtual;
function geTSymtable(t:tgeTSymtable):TSymtable;virtual;
function is_publishable:boolean;virtual;abstract;
function needs_inittable:boolean;virtual;abstract;
function is_related(def:tdef):boolean;virtual;
procedure ChangeOwner(st:TSymtable);
procedure register_created_object_type;virtual;
end;
{************************************************
TSym
************************************************}
{ this object is the base for all symbol objects }
{ tsym }
tsym = class(TSymEntry)
protected
public
fileinfo : tfileposinfo;
symoptions : tsymoptions;
visibility : tvisibility;
refs : longint;
reflist : TLinkedList;
isdbgwritten : boolean;
constructor create(st:tsymtyp;const aname:string);
destructor destroy;override;
function mangledname:string; virtual;
procedure buildderef;virtual;
procedure deref;virtual;
procedure ChangeOwner(st:TSymtable);
procedure IncRefCount;
procedure IncRefCountBy(AValue : longint);
procedure MaybeCreateRefList;
procedure AddRef;
end;
tsymarr = array[0..maxlongint div sizeof(pointer)-1] of tsym;
psymarr = ^tsymarr;
{************************************************
TDeref
************************************************}
tderef = object
dataidx : longint;
procedure reset;
procedure build(s:TObject);
function resolve:TObject;
end;
{************************************************
tpropaccesslist
************************************************}
ppropaccesslistitem = ^tpropaccesslistitem;
tpropaccesslistitem = record
sltype : tsltype;
next : ppropaccesslistitem;
case byte of
0 : (sym : tsym; symderef : tderef);
1 : (value : TConstExprInt; valuedef: tdef; valuedefderef:tderef);
2 : (def: tdef; defderef:tderef);
end;
tpropaccesslist = class
procdef : tdef;
procdefderef : tderef;
firstsym,
lastsym : ppropaccesslistitem;
constructor create;
destructor destroy;override;
function empty:boolean;
procedure addsym(slt:tsltype;p:tsym);
procedure addconst(slt:tsltype;v:TConstExprInt;d:tdef);
procedure addtype(slt:tsltype;d:tdef);
procedure addsymderef(slt:tsltype;d:tderef);
procedure addconstderef(slt:tsltype;v:TConstExprInt;d:tderef);
procedure addtypederef(slt:tsltype;d:tderef);
procedure clear;
procedure resolve;
procedure buildderef;
end;
{************************************************
Tcompilerppufile
************************************************}
tcompilerppufile=class(tppufile)
public
procedure checkerror;
procedure getguid(var g: tguid);
function getexprint:Tconstexprint;
function getptruint:TConstPtrUInt;
procedure getposinfo(var p:tfileposinfo);
procedure getderef(var d:tderef);
function getpropaccesslist:tpropaccesslist;
function getasmsymbol:tasmsymbol;
procedure putguid(const g: tguid);
procedure putexprint(const v:tconstexprint);
procedure PutPtrUInt(v:TConstPtrUInt);
procedure putposinfo(const p:tfileposinfo);
procedure putderef(const d:tderef);
procedure putpropaccesslist(p:tpropaccesslist);
procedure putasmsymbol(s:tasmsymbol);
end;
{$ifdef MEMDEBUG}
var
memmanglednames,
memprocpara,
memprocparast,
memproclocalst,
memprocnodetree : tmemdebug;
{$endif MEMDEBUG}
function FindUnitSymtable(st:TSymtable):TSymtable;
implementation
uses
crefs,
verbose,
fmodule
;
{****************************************************************************
Utils
****************************************************************************}
function FindUnitSymtable(st:TSymtable):TSymtable;
begin
result:=nil;
repeat
if not assigned(st) then
internalerror(200602034);
case st.symtabletype of
localmacrosymtable,
exportedmacrosymtable,
staticsymtable,
globalsymtable :
begin
result:=st;
exit;
end;
recordsymtable,
localsymtable,
parasymtable,
ObjectSymtable :
st:=st.defowner.owner;
else
internalerror(200602035);
end;
until false;
end;
{****************************************************************************
Tdef
****************************************************************************}
constructor tdef.create(dt:tdeftyp);
begin
inherited create;
typ:=dt;
owner := nil;
typesym := nil;
defoptions:=[];
dbg_state:=dbg_state_unused;
stab_number:=0;
end;
function tdef.typename:string;
begin
if assigned(typesym) and
not(typ in [procvardef,procdef]) and
(typesym.realname[1]<>'$') then
result:=typesym.realname
else
result:=GetTypeName;
end;
function tdef.GetTypeName : string;
begin
GetTypeName:='<unknown type>'
end;
function tdef.mangledparaname:string;
begin
if assigned(typesym) then
mangledparaname:=typesym.name
else
mangledparaname:=getmangledparaname;
end;
function tdef.getmangledparaname:string;
begin
result:='<unknown type>';
end;
function tdef.getparentdef:tdef;
begin
result:=nil;
end;
function tdef.geTSymtable(t:tgeTSymtable):TSymtable;
begin
result:=nil;
end;
function tdef.is_related(def:tdef):boolean;
begin
result:=false;
end;
function tdef.packedbitsize:aint;
begin
result:=size * 8;
end;
procedure tdef.ChangeOwner(st:TSymtable);
begin
// if assigned(Owner) then
// Owner.DefList.List[i]:=nil;
Owner:=st;
Owner.DefList.Add(self);
end;
procedure tdef.register_created_object_type;
begin
end;
{****************************************************************************
TSYM (base for all symtypes)
****************************************************************************}
constructor tsym.create(st:tsymtyp;const aname:string);
begin
inherited CreateNotOwned;
realname:=aname;
typ:=st;
RefList:=nil;
symoptions:=[];
fileinfo:=current_tokenpos;
isdbgwritten := false;
visibility:=vis_public;
end;
destructor Tsym.destroy;
begin
if assigned(RefList) then
RefList.Free;
inherited Destroy;
end;
procedure Tsym.IncRefCount;
begin
inc(refs);
if cs_browser in current_settings.moduleswitches then
begin
MaybeCreateRefList;
AddRef;
end;
end;
procedure Tsym.IncRefCountBy(AValue : longint);
begin
inc(refs,AValue);
end;
procedure Tsym.MaybeCreateRefList;
begin
if not assigned(reflist) then
reflist:=TRefLinkedList.create;
end;
procedure Tsym.AddRef;
var
RefItem: TRefItem;
begin
RefItem:=TRefItem.Create(current_tokenpos);
RefList.Concat(RefItem);
end;
procedure Tsym.buildderef;
begin
end;
procedure Tsym.deref;
begin
end;
function tsym.mangledname : string;
begin
internalerror(200204171);
result:='';
end;
procedure tsym.ChangeOwner(st:TSymtable);
begin
Owner:=st;
inherited ChangeOwner(Owner.SymList);
end;
{****************************************************************************
tpropaccesslist
****************************************************************************}
constructor tpropaccesslist.create;
begin
procdef:=nil; { needed for procedures }
firstsym:=nil;
lastsym:=nil;
end;
destructor tpropaccesslist.destroy;
begin
clear;
end;
function tpropaccesslist.empty:boolean;
begin
empty:=(firstsym=nil);
end;
procedure tpropaccesslist.clear;
var
hp : ppropaccesslistitem;
begin
while assigned(firstsym) do
begin
hp:=firstsym;
firstsym:=firstsym^.next;
dispose(hp);
end;
firstsym:=nil;
lastsym:=nil;
procdef:=nil;
end;
procedure tpropaccesslist.addsym(slt:tsltype;p:tsym);
var
hp : ppropaccesslistitem;
begin
new(hp);
fillchar(hp^,sizeof(tpropaccesslistitem),0);
hp^.sltype:=slt;
hp^.sym:=p;
hp^.symderef.reset;
if assigned(lastsym) then
lastsym^.next:=hp
else
firstsym:=hp;
lastsym:=hp;
end;
procedure tpropaccesslist.addconst(slt:tsltype;v:TConstExprInt;d:tdef);
var
hp : ppropaccesslistitem;
begin
new(hp);
fillchar(hp^,sizeof(tpropaccesslistitem),0);
hp^.sltype:=slt;
hp^.value:=v;
hp^.valuedef:=d;
hp^.valuedefderef.reset;
if assigned(lastsym) then
lastsym^.next:=hp
else
firstsym:=hp;
lastsym:=hp;
end;
procedure tpropaccesslist.addtype(slt:tsltype;d:tdef);
var
hp : ppropaccesslistitem;
begin
new(hp);
fillchar(hp^,sizeof(tpropaccesslistitem),0);
hp^.sltype:=slt;
hp^.def:=d;
hp^.defderef.reset;
if assigned(lastsym) then
lastsym^.next:=hp
else
firstsym:=hp;
lastsym:=hp;
end;
procedure tpropaccesslist.addsymderef(slt:tsltype;d:tderef);
begin
addsym(slt,nil);
lastsym^.symderef:=d;
end;
procedure tpropaccesslist.addconstderef(slt:tsltype;v:TConstExprInt;d:tderef);
begin
addconst(slt,v,nil);
lastsym^.valuedefderef:=d;
end;
procedure tpropaccesslist.addtypederef(slt:tsltype;d:tderef);
begin
addtype(slt,nil);
lastsym^.defderef:=d;
end;
procedure tpropaccesslist.resolve;
var
hp : ppropaccesslistitem;
begin
procdef:=tdef(procdefderef.resolve);
hp:=firstsym;
while assigned(hp) do
begin
case hp^.sltype of
sl_call,
sl_load,
sl_subscript :
hp^.sym:=tsym(hp^.symderef.resolve);
sl_absolutetype,
sl_typeconv :
hp^.def:=tdef(hp^.defderef.resolve);
sl_vec:
hp^.valuedef:=tdef(hp^.valuedefderef.resolve);
else
internalerror(200110205);
end;
hp:=hp^.next;
end;
end;
procedure tpropaccesslist.buildderef;
var
hp : ppropaccesslistitem;
begin
procdefderef.build(procdef);
hp:=firstsym;
while assigned(hp) do
begin
case hp^.sltype of
sl_call,
sl_load,
sl_subscript :
hp^.symderef.build(hp^.sym);
sl_absolutetype,
sl_typeconv :
hp^.defderef.build(hp^.def);
sl_vec:
hp^.valuedefderef.build(hp^.valuedef);
else
internalerror(200110205);
end;
hp:=hp^.next;
end;
end;
{****************************************************************************
Tderef
****************************************************************************}
procedure tderef.reset;
begin
dataidx:=-1;
end;
procedure tderef.build(s:TObject);
var
len : byte;
st : TSymtable;
data : array[0..255] of byte;
idx : word;
begin
{ skip length byte }
len:=1;
if assigned(s) then
begin
{ TODO: ugly hack}
if s is tsym then
st:=FindUnitSymtable(tsym(s).owner)
else
st:=FindUnitSymtable(tdef(s).owner);
if not st.iscurrentunit then
begin
{ register that the unit is needed for resolving }
data[len]:=ord(deref_unit);
idx:=current_module.derefidx_unit(st.moduleid);
data[len+1]:=idx shr 8 and $ff;
data[len+2]:=idx and $ff;
inc(len,3);
end;
if s is tsym then
begin
data[len]:=ord(deref_symid);
data[len+1]:=tsym(s).symid shr 24 and $ff;
data[len+2]:=tsym(s).symid shr 16 and $ff;
data[len+3]:=tsym(s).symid shr 8 and $ff;
data[len+4]:=tsym(s).symid and $ff;
inc(len,5);
end
else
begin
data[len]:=ord(deref_defid);
data[len+1]:=tdef(s).defid shr 24 and $ff;
data[len+2]:=tdef(s).defid shr 16 and $ff;
data[len+3]:=tdef(s).defid shr 8 and $ff;
data[len+4]:=tdef(s).defid and $ff;
inc(len,5);
end;
end
else
begin
{ nil pointer }
data[len]:=ord(deref_nil);
inc(len);
end;
{ store data length in first byte }
data[0]:=len-1;
{ store index and write to derefdata }
dataidx:=current_module.derefdata.size;
current_module.derefdata.write(data,len);
end;
function tderef.resolve:TObject;
var
pm : tmodule;
typ : tdereftype;
idx : longint;
i : aint;
len : byte;
data : array[0..255] of byte;
begin
result:=nil;
{ not initialized or error }
if dataidx<0 then
internalerror(200306067);
{ read data }
current_module.derefdata.seek(dataidx);
if current_module.derefdata.read(len,1)<>1 then
internalerror(200310221);
if len>0 then
begin
if current_module.derefdata.read(data,len)<>len then
internalerror(200310222);
end;
{ process data }
pm:=current_module;
i:=0;
while (i<len) do
begin
typ:=tdereftype(data[i]);
inc(i);
case typ of
deref_unit :
begin
idx:=(data[i] shl 8) or data[i+1];
inc(i,2);
pm:=current_module.resolve_unit(idx);
end;
deref_defid :
begin
idx:=longint((data[i] shl 24) or (data[i+1] shl 16) or (data[i+2] shl 8) or data[i+3]);
inc(i,4);
result:=tdef(pm.deflist[idx]);
end;
deref_symid :
begin
idx:=longint((data[i] shl 24) or (data[i+1] shl 16) or (data[i+2] shl 8) or data[i+3]);
inc(i,4);
result:=tsym(pm.symlist[idx]);
end;
deref_nil :
begin
result:=nil;
{ Only allowed when no other deref is available }
if len<>1 then
internalerror(200306232);
end;
else
internalerror(200212277);
end;
end;
end;
{*****************************************************************************
TCompilerPPUFile
*****************************************************************************}
procedure tcompilerppufile.checkerror;
begin
if error then
Message(unit_f_ppu_read_error);
end;
procedure tcompilerppufile.getguid(var g: tguid);
begin
longint(g.d1):=getlongint;
g.d2:=getword;
g.d3:=getword;
getdata(g.d4,sizeof(g.d4));
end;
function tcompilerppufile.getexprint:Tconstexprint;
begin
getexprint.overflow:=false;
getexprint.signed:=boolean(getbyte);
getexprint.svalue:=getint64;
end;
function tcompilerppufile.getPtrUInt:TConstPtrUInt;
begin
{$if sizeof(TConstPtrUInt)=8}
result:=tconstptruint(getint64);
{$else}
result:=TConstPtrUInt(getlongint);
{$endif}
end;
procedure tcompilerppufile.getposinfo(var p:tfileposinfo);
var
info : byte;
begin
{
info byte layout in bits:
0-1 - amount of bytes for fileindex
2-3 - amount of bytes for line
4-5 - amount of bytes for column
}
info:=getbyte;
case (info and $03) of
0 : p.fileindex:=getbyte;
1 : p.fileindex:=getword;
2 : p.fileindex:=(getbyte shl 16) or getword;
3 : p.fileindex:=getlongint;
end;
case ((info shr 2) and $03) of
0 : p.line:=getbyte;
1 : p.line:=getword;
2 : p.line:=(getbyte shl 16) or getword;
3 : p.line:=getlongint;
end;
case ((info shr 4) and $03) of
0 : p.column:=getbyte;
1 : p.column:=getword;
2 : p.column:=(getbyte shl 16) or getword;
3 : p.column:=getlongint;
end;
p.moduleindex:=current_module.unit_index;
end;
procedure tcompilerppufile.getderef(var d:tderef);
begin
d.dataidx:=getlongint;
end;
function tcompilerppufile.getpropaccesslist:tpropaccesslist;
var
hderef : tderef;
slt : tsltype;
idx : longint;
p : tpropaccesslist;
begin
p:=tpropaccesslist.create;
getderef(p.procdefderef);
repeat
slt:=tsltype(getbyte);
case slt of
sl_none :
break;
sl_call,
sl_load,
sl_subscript :
begin
getderef(hderef);
p.addsymderef(slt,hderef);
end;
sl_absolutetype,
sl_typeconv :
begin
getderef(hderef);
p.addtypederef(slt,hderef);
end;
sl_vec :
begin
idx:=getlongint;
getderef(hderef);
p.addconstderef(slt,idx,hderef);
end;
else
internalerror(200110204);
end;
until false;
getpropaccesslist:=tpropaccesslist(p);
end;
function tcompilerppufile.getasmsymbol:tasmsymbol;
begin
getlongint;
getasmsymbol:=nil;
end;
procedure tcompilerppufile.putposinfo(const p:tfileposinfo);
var
oldcrc : boolean;
info : byte;
begin
{ posinfo is not relevant for changes in PPU }
oldcrc:=do_crc;
do_crc:=false;
{
info byte layout in bits:
0-1 - amount of bytes for fileindex
2-3 - amount of bytes for line
4-5 - amount of bytes for column
}
info:=0;
{ calculate info byte }
if (p.fileindex>$ff) then
begin
info:=info or $1;
{ uncomment this code if tfileposinfo.fileindex type was changed
if (p.fileindex<=$ffff) then
info:=info or $1
else
if (p.fileindex<=$ffffff) then
info:=info or $2
else
info:=info or $3;
}
end;
if (p.line>$ff) then
begin
if (p.line<=$ffff) then
info:=info or $4
else
if (p.line<=$ffffff) then
info:=info or $8
else
info:=info or $c;
end;
if (p.column>$ff) then
begin
info:=info or $10;
{ uncomment this code if tfileposinfo.column type was changed
if (p.column<=$ffff) then
info:=info or $10
else
if (p.column<=$ffffff) then
info:=info or $20
else
info:=info or $30;
}
end;
{ write data }
putbyte(info);
case (info and $03) of
0 : putbyte(p.fileindex);
1 : putword(p.fileindex);
2 : begin
putbyte(p.fileindex shr 16);
putword(p.fileindex and $ffff);
end;
3 : putlongint(p.fileindex);
end;
case ((info shr 2) and $03) of
0 : putbyte(p.line);
1 : putword(p.line);
2 : begin
putbyte(p.line shr 16);
putword(p.line and $ffff);
end;
3 : putlongint(p.line);
end;
case ((info shr 4) and $03) of
0 : putbyte(p.column);
1 : putword(p.column);
2 : begin
putbyte(p.column shr 16);
putword(p.column and $ffff);
end;
3 : putlongint(p.column);
end;
do_crc:=oldcrc;
end;
procedure tcompilerppufile.putguid(const g: tguid);
begin
putlongint(longint(g.d1));
putword(g.d2);
putword(g.d3);
putdata(g.d4,sizeof(g.d4));
end;
procedure Tcompilerppufile.putexprint(const v:Tconstexprint);
begin
if v.overflow then
internalerror(200706102);
putbyte(byte(v.signed));
putint64(v.svalue);
end;
procedure tcompilerppufile.PutPtrUInt(v:TConstPtrUInt);
begin
{$if sizeof(TConstPtrUInt)=8}
putint64(int64(v));
{$else}
{$if sizeof(TConstPtrUInt)=4}
putlongint(longint(v));
{$else}
internalerror(2002082601);
{$endif} {$endif}
end;
procedure tcompilerppufile.putderef(const d:tderef);
var
oldcrc : boolean;
begin
oldcrc:=do_crc;
do_crc:=false;
putlongint(d.dataidx);
do_crc:=oldcrc;
end;
procedure tcompilerppufile.putpropaccesslist(p:tpropaccesslist);
var
hp : ppropaccesslistitem;
begin
putderef(p.procdefderef);
hp:=p.firstsym;
while assigned(hp) do
begin
putbyte(byte(hp^.sltype));
case hp^.sltype of
sl_call,
sl_load,
sl_subscript :
putderef(hp^.symderef);
sl_absolutetype,
sl_typeconv :
putderef(hp^.defderef);
sl_vec :
begin
putlongint(int64(hp^.value));
putderef(hp^.valuedefderef);
end;
else
internalerror(200110205);
end;
hp:=hp^.next;
end;
putbyte(byte(sl_none));
end;
procedure tcompilerppufile.putasmsymbol(s:tasmsymbol);
begin
putlongint(0);
end;
{$ifdef MEMDEBUG}
initialization
memmanglednames:=TMemDebug.create('Manglednames');
memmanglednames.stop;
memprocpara:=TMemDebug.create('ProcPara');
memprocpara.stop;
memprocparast:=TMemDebug.create('ProcParaSt');
memprocparast.stop;
memproclocalst:=TMemDebug.create('ProcLocalSt');
memproclocalst.stop;
memprocnodetree:=TMemDebug.create('ProcNodeTree');
memprocnodetree.stop;
finalization
memmanglednames.free;
memprocpara.free;
memprocparast.free;
memproclocalst.free;
memprocnodetree.free;
{$endif MEMDEBUG}
end.