fpc/compiler/tree.pas
1998-03-25 11:18:12 +00:00

1252 lines
37 KiB
ObjectPascal

{
$Id$
Copyright (c) 1993-98 by Florian Klaempfl
This units exports some routines to manage the parse tree
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.
****************************************************************************
}
{$ifdef tp}
{E+,N+}
{$endif}
unit tree;
interface
uses
objects,globals,symtable,cobjects,verbose,aasm,files
{$ifdef i386}
,i386
{$endif}
{$ifdef m68k}
,m68k
{$endif}
{$ifdef alpha}
,alpha
{$endif}
;
type
tconstset = array[0..31] of byte;
pconstset = ^tconstset;
ttreetyp = (addn, {Represents the + operator.}
muln, {Represents the * operator.}
subn, {Represents the - operator.}
divn, {Represents the div operator.}
symdifn, {Represents the >< operator.}
modn, {Represents the mod operator.}
assignn, {Represents an assignment.}
loadn, {Represents the use of a variabele.}
rangen, {Represents a range (i.e. 0..9).}
ltn, {Represents the < operator.}
lten, {Represents the <= operator.}
gtn, {Represents the > operator.}
gten, {Represents the >= operator.}
equaln, {Represents the = operator.}
unequaln, {Represents the <> operator.}
inn, {Represents the in operator.}
orn, {Represents the or operator.}
xorn, {Represents the xor operator.}
shrn, {Represents the shr operator.}
shln, {Represents the shl operator.}
slashn, {Represents the / operator.}
andn, {Represents the and operator.}
subscriptn, {??? Field in a record/object?}
derefn, {Dereferences a pointer.}
addrn, {Represents the @ operator.}
doubleaddrn, {Represents the @@ operator.}
ordconstn, {Represents an ordinal value.}
typeconvn, {Represents type-conversion/typecast.}
calln, {Represents a call node.}
callparan, {Represents a parameter.}
realconstn, {Represents a real value.}
fixconstn, {Represents a fixed value.}
umminusn, {Represents a sign change (i.e. -2).}
asmn, {Represents an assembler node }
vecn, {Represents array indexing.}
stringconstn, {Represents a string constant.}
funcretn, {Represents the function result var.}
selfn, {Represents the self parameter.}
notn, {Represents the not operator.}
inlinen, {Internal procedures (i.e. writeln).}
niln, {Represents the nil pointer.}
errorn, {This part of the tree could not be
parsed because of a compiler error.}
typen, {A type name. Used for i.e. typeof(obj).}
hnewn, {The new operation, constructor call.}
hdisposen, {The dispose operation with destructor call.}
newn, {The new operation, constructor call.}
simpledisposen, {The dispose operation.}
setelen, {A set element (i.e. [a,b]).}
setconstrn, {A set constant (i.e. [1,2]).}
blockn, {A block of statements.}
anwein, {A linear list of nodes.}
loopn, { used in genloopnode, must be converted }
ifn, {An if statement.}
breakn, {A break statement.}
continuen, {A continue statement.}
repeatn, {A repeat until block.}
whilen, {A while do statement.}
forn, {A for loop.}
exitn, {An exit statement.}
withn, {A with statement.}
casen, {A case statement.}
labeln, {A label.}
goton, {A goto statement.}
simplenewn, {The new operation.}
tryexceptn, {A try except block.}
raisen, {A raise statement.}
switchesn, {??? Currently unused...}
tryfinallyn, {A try finally statement.}
isn, {Represents the is operator.}
asn, {Represents the as typecast.}
caretn, {Represents the ^ operator.}
failn, {Represents the fail statement.}
{ added for optimizations where we cannot suppress }
nothingn,
loadvmtn); {???.}
tconverttype = (tc_equal,tc_not_possible,tc_u8bit_2_s32bit,
tc_only_rangechecks32bit,tc_s8bit_2_s32bit,
tc_u16bit_2_s32bit,tc_s16bit_2_s32bit,
tc_s32bit_2_s16bit,tc_s32bit_2_u8bit,
tc_s32bit_2_u16bit,tc_string_to_string,
tc_cstring_charpointer,tc_string_chararray,
tc_array_to_pointer,tc_pointer_to_array,
tc_char_to_string,tc_u8bit_2_s16bit,
tc_u8bit_2_u16bit,tc_s8bit_2_s16bit,
tc_s16bit_2_s8bit,tc_s16bit_2_u8bit,
tc_u16bit_2_s8bit,tc_u16bit_2_u8bit,
tc_s8bit_2_u16bit,tc_s32bit_2_s8bit,
tc_s32bit_2_u32bit,tc_s16bit_2_u32bit,
tc_s8bit_2_u32bit,tc_u16bit_2_u32bit,
tc_u8bit_2_u32bit,tc_u32bit_2_s32bit,
tc_int_2_real,tc_real_2_fix,
tc_fix_2_real,tc_int_2_fix,tc_real_2_real,
tc_chararray_2_string,tc_bool_2_u8bit,
tc_proc2procvar,
tc_cchar_charpointer);
{ allows to determine which elementes are to be replaced }
tdisposetyp = (dt_nothing,dt_leftright,dt_left,
dt_mbleft,dt_string,dt_typeconv,dt_inlinen,
dt_mbleft_and_method,dt_constset,dt_loop,dt_case,
dt_with);
{ different assignment types }
tassigntyp = (at_normal,at_plus,at_minus,at_star,at_slash);
pcaserecord = ^tcaserecord;
tcaserecord = record
{ range }
_low,_high : longint;
{ only used by gentreejmp }
_at : plabel;
{ label of instruction }
statement : plabel;
{ left and right tree node }
less,greater : pcaserecord;
end;
ptree = ^ttree;
ttree = record
error : boolean;
disposetyp : tdisposetyp;
{ is true, if the right and left operand are swaped }
swaped : boolean;
{ the location of the result of this node }
location : tlocation;
{ the number of registers needed to evalute the node }
registers32,registersfpu : longint; { must be longint !!!! }
{$ifdef SUPPORT_MMX}
registersmmx : longint;
{$endif SUPPORT_MMX}
left,right : ptree;
resulttype : pdef;
inputfile : pinputfile;
{$ifdef TP}
line:word;
{$else}
line : longint;
{$endif}
pragmas : Tcswitches;
{$ifdef extdebug}
firstpasscount : longint;
{$endif extdebug}
case treetype : ttreetyp of
callparan : (is_colon_para : boolean;exact_match_found : boolean);
assignn : (assigntyp : tassigntyp);
loadn : (symtableentry : psym;symtable : psymtable;
is_absolute,is_first : boolean);
calln : (symtableprocentry : pprocsym;
symtableproc : psymtable;procdefinition : pprocdef;
methodpointer : ptree;
unit_specific : boolean);
ordconstn : (value : longint);
realconstn : (valued : bestreal;labnumber : longint;realtyp : tait);
fixconstn : (valuef: longint);
{$ifdef TEST_FUNCRET}
funcretn : (funcretprocinfo : pointer;retdef : pdef);
{$endif TEST_FUNCRET}
subscriptn : (vs : pvarsym);
vecn : (memindex,memseg:boolean);
stringconstn : (values : pstring;labstrnumber : longint);
typeconvn : (convtyp : tconverttype;explizit : boolean);
inlinen : (inlinenumber : longint);
{ procinlinen : (proc : pprocsym); }
setconstrn : (constset : pconstset);
loopn : (t1,t2 : ptree;backward : boolean);
asmn : (p_asm : paasmoutput);
casen : (nodes : pcaserecord;elseblock : ptree);
labeln,goton : (labelnr : plabel);
withn : (withsymtable : psymtable;tablecount : longint);
end;
procedure init_tree;
function gennode(t : ttreetyp;l,r : ptree) : ptree;
function genlabelnode(t : ttreetyp;nr : plabel) : ptree;
function genloadnode(v : pvarsym;st : psymtable) : ptree;
function gensinglenode(t : ttreetyp;l : ptree) : ptree;
function gensubscriptnode(varsym : pvarsym;l : ptree) : ptree;
function genordinalconstnode(v : longint;def : pdef) : ptree;
function genfixconstnode(v : longint;def : pdef) : ptree;
function gentypeconvnode(node : ptree;t : pdef) : ptree;
function gencallparanode(expr,next : ptree) : ptree;
function genrealconstnode(v : bestreal) : ptree;
function gencallnode(v : pprocsym;st : psymtable) : ptree;
function genmethodcallnode(v : pprocsym;st : psymtable;mp : ptree) : ptree;
function genstringconstnode(const s : string) : ptree;
function genzeronode(t : ttreetyp) : ptree;
function geninlinenode(number : longint;l : ptree) : ptree;
{
function genprocinlinenode(code : ptree;procsym : pprocsym) : ptree;
}
function gentypedconstloadnode(sym : ptypedconstsym;st : psymtable) : ptree;
function genenumnode(v : penumsym) : ptree;
function genselfnode(_class : pdef) : ptree;
function gensetconstruktnode(s : pconstset;settype : psetdef) : ptree;
function genloopnode(t : ttreetyp;l,r,n1: ptree;back : boolean) : ptree;
function genasmnode(p_asm : paasmoutput) : ptree;
function gencasenode(l,r : ptree;nodes : pcaserecord) : ptree;
function genwithnode(symtable : psymtable;l,r : ptree;count : longint) : ptree;
function getcopy(p : ptree) : ptree;
function equal_trees(t1,t2 : ptree) : boolean;
procedure disposetree(p : ptree);
procedure putnode(p : ptree);
function getnode : ptree;
procedure clearnodes;
procedure set_location(var destloc,sourceloc : tlocation);
procedure swap_location(var destloc,sourceloc : tlocation);
procedure set_file_line(from,_to : ptree);
{$ifdef extdebug}
const
maxfirstpasscount : longint = 0;
{$endif extdebug}
{$I innr.inc}
implementation
const
oldswitches : tcswitches = [];
{****************************************************************************
this is a pool for the tree nodes to get more performance
****************************************************************************}
var
root : ptree;
procedure init_tree;
begin
root:=nil;
end;
procedure clearnodes;
var
hp : ptree;
begin
hp:=root;
while assigned(hp) do
begin
root:=hp^.left;
dispose(hp);
hp:=root;
end;
end;
function getnode : ptree;
var
hp : ptree;
begin
if root=nil then
new(hp)
else
begin
hp:=root;
root:=root^.left;
end;
{ makes error tracking easier }
fillchar(hp^,sizeof(ttree),#0);
hp^.location.loc:=LOC_INVALID;
{ new node is error free }
hp^.error:=false;
{ we know also the position }
hp^.line:=current_module^.current_inputfile^.line_no;
hp^.inputfile:=current_module^.current_inputfile;
hp^.pragmas:=aktswitches;
getnode:=hp;
end;
procedure putnode(p : ptree);
begin
{ clean up the contents of a node }
if p^.treetype=asmn then
if assigned(p^.p_asm) then
dispose(p^.p_asm,done);
if p^.treetype=setconstrn then
if assigned(p^.constset) then
dispose(p^.constset);
if (p^.location.loc=LOC_MEM) or (p^.location.loc=LOC_REFERENCE) and
assigned(p^.location.reference.symbol) then
stringdispose(p^.location.reference.symbol);
if p^.disposetyp=dt_string then
stringdispose(p^.values);
{$ifdef extdebug}
if p^.firstpasscount>maxfirstpasscount then
maxfirstpasscount:=p^.firstpasscount;
dispose(p);
{$else extdebug}
p^.left:=root;
root:=p;
{$endif extdebug}
end;
function getcopy(p : ptree) : ptree;
var
hp : ptree;
begin
hp:=getnode;
hp^:=p^;
if assigned(p^.location.reference.symbol) then
hp^.location.reference.symbol:=stringdup(p^.location.reference.symbol^);
case p^.disposetyp of
dt_leftright :
begin
if assigned(p^.left) then
hp^.left:=getcopy(p^.left);
if assigned(p^.right) then
hp^.right:=getcopy(p^.right);
end;
dt_nothing : ;
dt_left :
if assigned(p^.left) then
hp^.left:=getcopy(p^.left);
dt_mbleft :
if assigned(p^.left) then
hp^.left:=getcopy(p^.left);
dt_mbleft_and_method :
begin
if assigned(p^.left) then
hp^.left:=getcopy(p^.left);
hp^.methodpointer:=getcopy(p^.methodpointer);
end;
dt_loop :
begin
if assigned(p^.left) then
hp^.left:=getcopy(p^.left);
if assigned(p^.right) then
hp^.right:=getcopy(p^.right);
if assigned(p^.t1) then
hp^.t1:=getcopy(p^.t1);
if assigned(p^.t2) then
hp^.t2:=getcopy(p^.t2);
end;
dt_string : hp^.values:=stringdup(p^.values^);
dt_typeconv : hp^.left:=getcopy(p^.left);
dt_inlinen :
if assigned(p^.left) then
hp^.left:=getcopy(p^.left);
else internalerror(11);
end;
getcopy:=hp;
end;
procedure deletecaselabels(p : pcaserecord);
begin
if assigned(p^.greater) then
deletecaselabels(p^.greater);
if assigned(p^.less) then
deletecaselabels(p^.less);
dispose(p);
end;
procedure disposetree(p : ptree);
begin
if not(assigned(p)) then
exit;
case p^.disposetyp of
dt_leftright :
begin
if assigned(p^.left) then
disposetree(p^.left);
if assigned(p^.right) then
disposetree(p^.right);
end;
dt_case :
begin
if assigned(p^.left) then
disposetree(p^.left);
if assigned(p^.right) then
disposetree(p^.right);
if assigned(p^.nodes) then
deletecaselabels(p^.nodes);
if assigned(p^.elseblock) then
disposetree(p^.elseblock);
end;
dt_nothing : ;
dt_left :
if assigned(p^.left) then
disposetree(p^.left);
dt_mbleft :
if assigned(p^.left) then
disposetree(p^.left);
dt_mbleft_and_method :
begin
if assigned(p^.left) then disposetree(p^.left);
disposetree(p^.methodpointer);
end;
dt_string : stringdispose(p^.values);
dt_constset :
begin
if assigned(p^.constset) then
begin
dispose(p^.constset);
p^.constset:=nil;
end;
if assigned(p^.left) then
disposetree(p^.left);
end;
dt_typeconv : disposetree(p^.left);
dt_inlinen :
if assigned(p^.left) then
disposetree(p^.left);
dt_loop :
begin
if assigned(p^.left) then
disposetree(p^.left);
if assigned(p^.right) then
disposetree(p^.right);
if assigned(p^.t1) then
disposetree(p^.t1);
if assigned(p^.t2) then
disposetree(p^.t2);
end;
dt_with :
begin
if assigned(p^.left) then
disposetree(p^.left);
if assigned(p^.right) then
disposetree(p^.right);
if assigned(p^.withsymtable) then
dispose(p^.withsymtable,done);
end;
else internalerror(12);
end;
putnode(p);
end;
procedure set_file_line(from,_to : ptree);
begin
if from<>nil then
begin
_to^.line:=from^.line;
_to^.inputfile:=from^.inputfile;
end;
end;
function genwithnode(symtable : psymtable;l,r : ptree;count : longint) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_with;
p^.treetype:=withn;
p^.left:=l;
p^.right:=r;
p^.registers32:=0;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.resulttype:=nil;
p^.withsymtable:=symtable;
p^.tablecount:=count;
set_file_line(l,p);
genwithnode:=p;
end;
function genfixconstnode(v : longint;def : pdef) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_nothing;
p^.treetype:=fixconstn;
p^.registers32:=0;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.resulttype:=def;
p^.value:=v;
genfixconstnode:=p;
end;
function gencallparanode(expr,next : ptree) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_leftright;
p^.treetype:=callparan;
p^.left:=expr;
p^.right:=next;
p^.registers32:=0;
{ p^.registers16:=0;
p^.registers8:=0; }
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.registersfpu:=0;
p^.resulttype:=nil;
p^.exact_match_found:=false;
p^.is_colon_para:=false;
set_file_line(expr,p);
gencallparanode:=p;
end;
function gennode(t : ttreetyp;l,r : ptree) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_leftright;
p^.treetype:=t;
p^.left:=l;
p^.right:=r;
p^.registers32:=0;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.resulttype:=nil;
gennode:=p;
end;
function gencasenode(l,r : ptree;nodes : pcaserecord) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_case;
p^.treetype:=casen;
p^.left:=l;
p^.right:=r;
p^.nodes:=nodes;
p^.registers32:=0;
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.resulttype:=nil;
set_file_line(l,p);
gencasenode:=p;
end;
function genloopnode(t : ttreetyp;l,r,n1 : ptree;back : boolean) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_loop;
p^.treetype:=t;
p^.left:=l;
p^.right:=r;
p^.t1:=n1;
p^.t2:=nil;
p^.registers32:=0;
p^.backward:=back;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.resulttype:=nil;
set_file_line(l,p);
genloopnode:=p;
end;
function genordinalconstnode(v : longint;def : pdef) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_nothing;
p^.treetype:=ordconstn;
p^.registers32:=0;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.resulttype:=def;
p^.value:=v;
genordinalconstnode:=p;
end;
function genenumnode(v : penumsym) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_nothing;
p^.treetype:=ordconstn;
p^.registers32:=0;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.resulttype:=v^.definition;
p^.value:=v^.value;
genenumnode:=p;
end;
function genrealconstnode(v : bestreal) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_nothing;
p^.treetype:=realconstn;
p^.registers32:=0;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
{$ifdef i386}
p^.resulttype:=c64floatdef;
p^.valued:=v;
{ default value is double }
p^.realtyp:=ait_real_64bit;
{$endif}
{$ifdef m68k}
p^.resulttype:=new(pfloatdef,init(s32real));
p^.valued:=v;
{ default value is double }
p^.realtyp:=ait_real_32bit;
{$endif}
p^.labnumber:=-1;
genrealconstnode:=p;
end;
function genstringconstnode(const s : string) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_string;
p^.treetype:=stringconstn;
p^.registers32:=0;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.resulttype:=cstringdef;
p^.values:=stringdup(s);
p^.labstrnumber:=-1;
genstringconstnode:=p;
end;
function gensinglenode(t : ttreetyp;l : ptree) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_left;
p^.treetype:=t;
p^.left:=l;
p^.registers32:=0;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.resulttype:=nil;
gensinglenode:=p;
end;
function genasmnode(p_asm : paasmoutput) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_nothing;
p^.treetype:=asmn;
p^.registers32:=4;
p^.p_asm:=p_asm;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.registersfpu:=8;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=8;
{$endif SUPPORT_MMX}
p^.resulttype:=nil;
genasmnode:=p;
end;
function genloadnode(v : pvarsym;st : psymtable) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.registers32:=0;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.treetype:=loadn;
p^.resulttype:=v^.definition;
p^.symtableentry:=v;
p^.symtable:=st;
p^.is_first := False;
p^.disposetyp:=dt_nothing;
genloadnode:=p;
end;
function gentypedconstloadnode(sym : ptypedconstsym;st : psymtable) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.registers32:=0;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.treetype:=loadn;
p^.resulttype:=sym^.definition;
p^.symtableentry:=pvarsym(sym);
p^.symtable:=st;
p^.disposetyp:=dt_nothing;
gentypedconstloadnode:=p;
end;
function gentypeconvnode(node : ptree;t : pdef) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_typeconv;
p^.treetype:=typeconvn;
p^.left:=node;
p^.registers32:=0;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.convtyp:=tc_equal;
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.resulttype:=t;
p^.convtyp:=tc_equal;
p^.explizit:=false;
set_file_line(node,p);
gentypeconvnode:=p;
end;
function gencallnode(v : pprocsym;st : psymtable) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.registers32:=0;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.treetype:=calln;
p^.symtableprocentry:=v;
p^.symtableproc:=st;
p^.unit_specific:=false;
p^.disposetyp := dt_leftright;
p^.methodpointer:=nil;
p^.left:=nil;
p^.right:=nil;
p^.procdefinition:=nil;
gencallnode:=p;
end;
function genmethodcallnode(v : pprocsym;st : psymtable;mp : ptree) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.registers32:=0;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.treetype:=calln;
p^.symtableprocentry:=v;
p^.symtableproc:=st;
p^.disposetyp:=dt_mbleft_and_method;
p^.left:=nil;
p^.right:=nil;
p^.methodpointer:=mp;
p^.procdefinition:=nil;
genmethodcallnode:=p;
end;
function gensubscriptnode(varsym : pvarsym;l : ptree) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_left;
p^.treetype:=subscriptn;
p^.left:=l;
p^.registers32:=0;
p^.vs:=varsym;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.resulttype:=nil;
gensubscriptnode:=p;
end;
function genzeronode(t : ttreetyp) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_nothing;
p^.treetype:=t;
p^.registers32:=0;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.resulttype:=nil;
genzeronode:=p;
end;
function genlabelnode(t : ttreetyp;nr : plabel) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_nothing;
p^.treetype:=t;
p^.registers32:=0;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.resulttype:=nil;
{ for security }
{ nr^.is_used:=true;}
p^.labelnr:=nr;
genlabelnode:=p;
end;
function genselfnode(_class : pdef) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_nothing;
p^.treetype:=selfn;
p^.registers32:=0;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.resulttype:=_class;
genselfnode:=p;
end;
function geninlinenode(number : longint;l : ptree) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_inlinen;
p^.treetype:=inlinen;
p^.left:=l;
p^.inlinenumber:=number;
p^.registers32:=0;
{ p^.registers16:=0;
p^.registers8:=0; }
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.resulttype:=nil;
geninlinenode:=p;
end;
{ function genprocinlinenode(code : ptree;proc : pprocsym) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_inlinen;
p^.treetype:=inlinen;
p^.inlineproc:=proc;
p^.left:=code;
p^.registers32:=code^.registers32;
p^.registersfpu:=code^.registersfpu;
$ifdef SUPPORT_MMX
p^.registersmmx:=0;
$endif SUPPORT_MMX
p^.resulttype:=proc^.definition^.returntype;
genprocinlinenode:=p;
end; }
function gensetconstruktnode(s : pconstset;settype : psetdef) : ptree;
var
p : ptree;
begin
p:=getnode;
p^.disposetyp:=dt_constset;
p^.treetype:=setconstrn;
p^.registers32:=0;
p^.registersfpu:=0;
{$ifdef SUPPORT_MMX}
p^.registersmmx:=0;
{$endif SUPPORT_MMX}
p^.resulttype:=settype;
p^.left:=nil;
new(p^.constset);
p^.constset^:=s^;
gensetconstruktnode:=p;
end;
function equal_trees(t1,t2 : ptree) : boolean;
begin
if t1^.treetype=t2^.treetype then
begin
case t1^.treetype of
addn,
muln,
equaln,
orn,
xorn,
andn,
unequaln:
begin
equal_trees:=(equal_trees(t1^.left,t2^.left) and
equal_trees(t1^.right,t2^.right)) or
(equal_trees(t1^.right,t2^.left) and
equal_trees(t1^.left,t2^.right));
end;
subn,
divn,
modn,
assignn,
ltn,
lten,
gtn,
gten,
inn,
shrn,
shln,
slashn,
rangen:
begin
equal_trees:=(equal_trees(t1^.left,t2^.left) and
equal_trees(t1^.right,t2^.right));
end;
umminusn,
notn,
derefn,
addrn:
begin
equal_trees:=(equal_trees(t1^.left,t2^.left));
end;
loadn:
begin
equal_trees:=(t1^.symtableentry=t2^.symtableentry)
{ not necessary
and (t1^.symtable=t2^.symtable)};
end;
{
subscriptn,
ordconstn,typeconvn,calln,callparan,
realconstn,asmn,vecn,
stringconstn,funcretn,selfn,
inlinen,niln,errorn,
typen,hnewn,hdisposen,newn,
disposen,setelen,setconstrn
}
else equal_trees:=false;
end;
end
else
equal_trees:=false;
end;
{This is needed if you want to be able to delete the string with the nodes !!}
procedure set_location(var destloc,sourceloc : tlocation);
begin
if assigned(destloc.reference.symbol) then
stringdispose(destloc.reference.symbol);
destloc:= sourceloc;
if sourceloc.loc in [LOC_MEM,LOC_REFERENCE] then
begin
if assigned(sourceloc.reference.symbol) then
destloc.reference.symbol:=
stringdup(sourceloc.reference.symbol^);
end
else
destloc.reference.symbol:=nil;
end;
procedure swap_location(var destloc,sourceloc : tlocation);
var
swapl : tlocation;
begin
swapl := destloc;
destloc := sourceloc;
sourceloc := swapl;
end;
end.
{
$Log$
Revision 1.1 1998-03-25 11:18:13 root
Initial revision
Revision 1.15 1998/03/24 21:48:36 florian
* just a couple of fixes applied:
- problem with fixed16 solved
- internalerror 10005 problem fixed
- patch for assembler reading
- small optimizer fix
- mem is now supported
Revision 1.14 1998/03/10 16:27:46 pierre
* better line info in stabs debug
* symtabletype and lexlevel separated into two fields of tsymtable
+ ifdef MAKELIB for direct library output, not complete
+ ifdef CHAINPROCSYMS for overloaded seach across units, not fully
working
+ ifdef TESTFUNCRET for setting func result in underfunction, not
working
Revision 1.13 1998/03/10 01:17:30 peter
* all files have the same header
* messages are fully implemented, EXTDEBUG uses Comment()
+ AG... files for the Assembler generation
Revision 1.12 1998/03/02 01:49:37 peter
* renamed target_DOS to target_GO32V1
+ new verbose system, merged old errors and verbose units into one new
verbose.pas, so errors.pas is obsolete
Revision 1.11 1998/02/27 09:26:18 daniel
* Changed symtable handling so no junk symtable is put on the symtablestack.
Revision 1.10 1998/02/13 10:35:54 daniel
* Made Motorola version compilable.
* Fixed optimizer
Revision 1.9 1998/02/12 11:50:51 daniel
Yes! Finally! After three retries, my patch!
Changes:
Complete rewrite of psub.pas.
Added support for DLL's.
Compiler requires less memory.
Platform units for each platform.
Revision 1.8 1998/02/04 14:39:31 florian
* small clean up
Revision 1.7 1998/01/13 23:11:16 florian
+ class methods
Revision 1.6 1998/01/11 04:16:36 carl
+ correct floating point support for m68k
Revision 1.5 1998/01/07 00:17:11 michael
Restored released version (plus fixes) as current
Revision 1.3 1997/12/04 12:02:15 pierre
+ added a counter of max firstpass's for a ptree
for debugging only in ifdef extdebug
Revision 1.2 1997/11/29 15:43:08 florian
* some minor changes
Revision 1.1.1.1 1997/11/27 08:33:03 michael
FPC Compiler CVS start
Pre-CVS log:
CEC Carl-Eric Codere
FK Florian Klaempfl
PM Pierre Muller
+ feature added
- removed
* bug fixed or changed
History:
19th october 1996:
+ adapted to version 0.9.0
6th september 1997:
+ added support for MC68000 (CEC)
3rd october 1997:
+ added tc_bool_2_u8bit for in_ord_x (PM)
3rd november1997:
+ added symdifn for sets (PM)
13th november 1997:
+ added partial code for u32bit support (PM)
}