* problem with previous REGALLOC solved

* improved property support
This commit is contained in:
florian 1998-04-09 22:16:33 +00:00
parent b69a1a8fd9
commit 50cbe1751e
5 changed files with 533 additions and 419 deletions

View File

@ -2080,7 +2080,6 @@ implementation
var
opsize : topsize;
{pushed,}withresult : boolean;
otlabel,hlabel,oflabel : plabel;
hregister : tregister;
loc : tloc;
@ -2090,7 +2089,6 @@ implementation
oflabel:=falselabel;
getlabel(truelabel);
getlabel(falselabel);
withresult:=false;
{ calculate left sides }
secondpass(p^.left);
case p^.left^.location.loc of
@ -2165,7 +2163,6 @@ implementation
{ we do not need destination anymore }
del_reference(p^.left^.location.reference);
{ only source if withresult is set }
if not(withresult) then
del_reference(p^.right^.location.reference);
loadstring(p);
ungetiftemp(p^.right^.location.reference);
@ -2197,8 +2194,7 @@ implementation
else
begin
concatcopy(p^.right^.location.reference,
p^.left^.location.reference,p^.left^.resulttype^.size,
withresult);
p^.left^.location.reference,p^.left^.resulttype^.size,false);
ungetiftemp(p^.right^.location.reference);
end;
end;
@ -2824,6 +2820,11 @@ implementation
exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,r,R_ESI)));
end;
{ direct call to class constructor, don't allocate memory }
if is_con_or_destructor and (p^.methodpointer^.resulttype^.deftype=objectdef) and
(pobjectdef(p^.methodpointer^.resulttype)^.isclass) then
exprasmlist^.concat(new(pai386,op_const(A_PUSH,S_L,0)))
else
exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_ESI)));
if is_con_or_destructor then
begin
@ -2960,6 +2961,7 @@ implementation
if ((aktprocsym^.properties and sp_static)<>0) or
((aktprocsym^.definition^.options and poclassmethod)<>0) or
((p^.procdefinition^.options and postaticmethod)<>0) or
((p^.procdefinition^.options and poconstructor)<>0) or
{ ESI is loaded earlier }
((p^.procdefinition^.options and poclassmethod)<>0)then
begin
@ -2979,6 +2981,9 @@ implementation
end;
end
else
{ aktprocsym should be assigned, also in main program }
internalerror(12345);
{
begin
new(r);
reset_reference(r^);
@ -2988,6 +2993,7 @@ implementation
reset_reference(r^);
r^.base:=R_EDI;
end;
}
if p^.procdefinition^.extnumber=-1 then
internalerror($Da);
r^.offset:=p^.procdefinition^.extnumber*4+12;
@ -5709,7 +5715,11 @@ do_jmp:
end.
{
$Log$
Revision 1.7 1998-04-09 14:28:05 jonas
Revision 1.8 1998-04-09 22:16:33 florian
* problem with previous REGALLOC solved
* improved property support
Revision 1.7 1998/04/09 14:28:05 jonas
+ basic k6 and 6x86 optimizing support (-O7 and -O8)
Revision 1.6 1998/04/08 11:34:20 peter

View File

@ -2410,7 +2410,7 @@ unit pass_1;
must_be_valid:=false;
firstpass(p^.left);
must_be_valid:=store_valid;
End;
end;
if not((p^.left^.resulttype^.deftype=stringdef) and
(defcoll^.data^.deftype=stringdef)) and
(defcoll^.data^.deftype<>formaldef) then
@ -2534,12 +2534,64 @@ unit pass_1;
procs:=nil;
{ made this global for disposing !! }
store_valid:=must_be_valid;
if not assigned(p^.procdefinition) then
begin
must_be_valid:=false;
{ procedure variable ? }
if not(assigned(p^.right)) then
if assigned(p^.right) then
begin
{ procedure does a call }
procinfo.flags:=procinfo.flags or pi_do_call;
{ calc the correture value for the register }
{$ifdef i386}
for regi:=R_EAX to R_EDI do
inc(reg_pushes[regi],t_times*2);
{$endif}
{$ifdef m68k}
for regi:=R_D0 to R_A6 do
inc(reg_pushes[regi],t_times*2);
{$endif}
{ calculate the type of the parameters }
if assigned(p^.left) then
begin
old_count_ref:=count_ref;
count_ref:=false;
firstcallparan(p^.left,nil);
count_ref:=old_count_ref;
if codegenerror then
exit;
end;
firstpass(p^.right);
{ check the parameters }
pdc:=pprocvardef(p^.right^.resulttype)^.para1;
pt:=p^.left;
while assigned(pdc) and assigned(pt) do
begin
pt:=pt^.right;
pdc:=pdc^.next;
end;
if assigned(pt) or assigned(pdc) then
Message(parser_e_illegal_parameter_list);
{ insert type conversions }
if assigned(p^.left) then
begin
old_count_ref:=count_ref;
count_ref:=true;
firstcallparan(p^.left,pprocvardef(p^.right^.resulttype)^.para1);
count_ref:=old_count_ref;
if codegenerror then
exit;
end;
p^.resulttype:=pprocvardef(p^.right^.resulttype)^.retdef;
{ this was missing, leads to a bug below if
the procvar is a function }
p^.procdefinition:=pprocdef(p^.right^.resulttype);
end
else
begin
{ determine the type of the parameters }
if assigned(p^.left) then
begin
old_count_ref:=count_ref;
@ -2552,6 +2604,11 @@ unit pass_1;
if codegenerror then
exit;
end;
{ do we know the procedure to call ? }
if not(assigned(p^.procdefinition)) then
begin
{ determine length of parameter list }
pt:=p^.left;
paralength:=0;
@ -2876,7 +2933,7 @@ unit pass_1;
p^.methodpointer:=nil;
end;
{$endif CHAINPROCSYMS}
end; { end of procedure to call determination }
{ work trough all parameters to insert the type conversions }
if assigned(p^.left) then
begin
@ -2885,6 +2942,7 @@ unit pass_1;
firstcallparan(p^.left,p^.procdefinition^.para1);
count_ref:=old_count_ref;
end;
{ handle predefined procedures }
if (p^.procdefinition^.options and pointernproc)<>0 then
begin
@ -2916,7 +2974,6 @@ unit pass_1;
{ calc the correture value for the register }
{$ifdef i386}
{ calc the correture value for the register }
for regi:=R_EAX to R_EDI do
begin
if (p^.procdefinition^.usedregisters and ($80 shr word(regi)))<>0 then
@ -2930,62 +2987,6 @@ unit pass_1;
inc(reg_pushes[regi],t_times*2);
end;
{$endif}
end
else
begin
{ procedure variable }
{ die Typen der Parameter berechnen }
{ procedure does a call }
procinfo.flags:=procinfo.flags or pi_do_call;
{$ifdef i386}
{ calc the correture value for the register }
for regi:=R_EAX to R_EDI do
inc(reg_pushes[regi],t_times*2);
{$endif}
{$ifdef m68k}
{ calc the correture value for the register }
for regi:=R_D0 to R_A6 do
inc(reg_pushes[regi],t_times*2);
{$endif}
if assigned(p^.left) then
begin
old_count_ref:=count_ref;
count_ref:=false;
firstcallparan(p^.left,nil);
count_ref:=old_count_ref;
if codegenerror then
exit;
end;
firstpass(p^.right);
{ check the parameters }
pdc:=pprocvardef(p^.right^.resulttype)^.para1;
pt:=p^.left;
while assigned(pdc) and assigned(pt) do
begin
pt:=pt^.right;
pdc:=pdc^.next;
end;
if assigned(pt) or assigned(pdc) then
Message(parser_e_illegal_parameter_list);
{ insert type conversions }
if assigned(p^.left) then
begin
old_count_ref:=count_ref;
count_ref:=true;
firstcallparan(p^.left,pprocvardef(p^.right^.resulttype)^.para1);
count_ref:=old_count_ref;
if codegenerror then
exit;
end;
p^.resulttype:=pprocvardef(p^.right^.resulttype)^.retdef;
{ this was missing , leads to a bug below if
the procvar is a function }
p^.procdefinition:=pprocdef(p^.right^.resulttype);
end;
end; { not assigned(p^.procdefinition) }
{ get a register for the return value }
@ -4495,7 +4496,11 @@ unit pass_1;
end.
{
$Log$
Revision 1.5 1998-04-08 16:58:04 pierre
Revision 1.6 1998-04-09 22:16:34 florian
* problem with previous REGALLOC solved
* improved property support
Revision 1.5 1998/04/08 16:58:04 pierre
* several bugfixes
ADD ADC and AND are also sign extended
nasm output OK (program still crashes at end

View File

@ -370,6 +370,7 @@ unit pdecl;
sc : pstringcontainer;
hp : pdef;
s : string;
pp : pprocdef;
begin
{ check for a class }
@ -471,8 +472,11 @@ unit pdecl;
{ take the whole info: }
p^.options:=ppropertysym(overriden)^.options;
p^.index:=ppropertysym(overriden)^.index;
p^.proptype:=ppropertysym(overriden)^.proptype;
p^.writeaccesssym:=ppropertysym(overriden)^.writeaccesssym;
p^.readaccesssym:=ppropertysym(overriden)^.readaccesssym;
p^.writeaccessdef:=ppropertysym(overriden)^.writeaccessdef;
p^.readaccessdef:=ppropertysym(overriden)^.readaccessdef;
end
else
begin
@ -480,6 +484,12 @@ unit pdecl;
message(parser_e_no_property_found_to_override);
end;
end;
{ create data defcoll to allow correct parameter checks }
new(datacoll);
datacoll^.paratyp:=vs_value;
datacoll^.data:=p^.proptype;
datacoll^.next:=nil;
if (token=ID) and (pattern='READ') then
begin
consume(ID);
@ -492,14 +502,27 @@ unit pdecl;
{ varsym aren't allowed for an indexed property
or an property with parameters }
if ((sym^.typ=varsym) and
(((p^.options and ppo_indexed)<>0) or
assigned(propertyparas))) or
{ not necessary, an index forces propertyparas
to be assigned
}
{ (((p^.options and ppo_indexed)<>0) or }
assigned(propertyparas)) or
not(sym^.typ in [varsym,procsym]) then
Message(parser_e_ill_property_access_sym);
{ search the matching definition }
if sym^.typ=procsym then
begin
{ !!!!!! }
pp:=get_procdef;
if not(assigned(pp)) or
not(is_equal(pp^.retdef,p^.proptype)) then
Message(parser_e_ill_property_access_sym);
p^.readaccessdef:=pp;
end
else if sym^.typ=varsym then
begin
if not(is_equal(pvarsym(sym)^.definition,
p^.proptype)) then
Message(parser_e_ill_property_access_sym);
end;
p^.readaccesssym:=sym;
end;
@ -513,16 +536,28 @@ unit pdecl;
Message1(sym_e_unknown_id,pattern)
else
begin
{ !!!! check sym }
if ((sym^.typ=varsym) and
(((p^.options and ppo_indexed)<>0)
{ or property paras })) or
assigned(propertyparas)) or
not(sym^.typ in [varsym,procsym]) then
Message(parser_e_ill_property_access_sym);
{ search the matching definition }
if sym^.typ=procsym then
begin
{ !!!!!! }
{ insert data entry to check access method }
datacoll^.next:=propertyparas;
propertyparas:=datacoll;
pp:=get_procdef;
{ ... and remove it }
propertyparas:=propertyparas^.next;
if not(assigned(pp)) then
Message(parser_e_ill_property_access_sym);
p^.writeaccessdef:=pp;
end
else if sym^.typ=varsym then
begin
if not(is_equal(pvarsym(sym)^.definition,
p^.proptype)) then
Message(parser_e_ill_property_access_sym);
end;
p^.writeaccesssym:=sym;
end;
@ -536,23 +571,7 @@ unit pdecl;
if (token=ID) and (pattern='DEFAULT') then
begin
consume(ID);
if token=SEMICOLON then
begin
p2:=search_default_property(aktclass);
if assigned(p2) then
message1(parser_e_only_one_default_property,
pobjectdef(p2^.owner^.defowner)^.name^)
else
begin
p^.options:=p^.options and ppo_defaultproperty;
if not(assigned(propertyparas)) then
message(parser_e_property_need_paras);
end;
end
else
begin
{ !!!!!!! storage }
end;
consume(SEMICOLON);
end
else if (token=ID) and (pattern='NODEFAULT') then
@ -561,14 +580,33 @@ unit pdecl;
{ !!!!!!!! }
end;
symtablestack^.insert(p);
{ default property ? }
consume(SEMICOLON);
if (token=ID) and (pattern='DEFAULT') then
begin
consume(ID);
p2:=search_default_property(aktclass);
if assigned(p2) then
message1(parser_e_only_one_default_property,
pobjectdef(p2^.owner^.defowner)^.name^)
else
begin
p^.options:=p^.options or ppo_defaultproperty;
if not(assigned(propertyparas)) then
message(parser_e_property_need_paras);
end;
consume(SEMICOLON);
end;
{ clean up }
if assigned(datacoll) then
dispose(datacoll);
end
else
begin
consume(ID);
consume(SEMICOLON);
end;
end;
procedure destructor_head;
@ -1689,7 +1727,11 @@ unit pdecl;
end.
{
$Log$
Revision 1.5 1998-04-08 14:59:20 florian
Revision 1.6 1998-04-09 22:16:35 florian
* problem with previous REGALLOC solved
* improved property support
Revision 1.5 1998/04/08 14:59:20 florian
* problem with new expr_type solved
Revision 1.4 1998/04/08 10:26:09 florian

View File

@ -418,60 +418,16 @@ unit pexpr;
afterassignment:=prevafterassn;
end;
{ the ID token has to be consumed before calling this function }
procedure do_member_read(const sym : psym;var p1 : ptree;
var pd : pdef;var again : boolean);
{ the following procedure handles the access to a property symbol }
procedure handle_propertysym(sym : psym;var p1 : ptree;
var pd : pdef);
var
static_name : string;
paras : ptree;
oldafterassignment,isclassref : boolean;
oldafterassignment : boolean;
p2 : ptree;
begin
if sym=nil then
begin
Message(sym_e_id_no_member);
disposetree(p1);
p1:=genzeronode(errorn);
{ try to clean up }
pd:=generrordef;
again:=false;
end
else
begin
isclassref:=pd^.deftype=classrefdef;
{ we assume, that only procsyms and varsyms are in an object }
{ symbol table, for classes, properties are allowed }
case sym^.typ of
procsym:
begin
p1:=genmethodcallnode(pprocsym(sym),srsymtable,p1);
do_proc_call(false,again,p1,pd);
{ now we know the real method e.g. we can check for }
{ a class method }
if isclassref and ((p1^.procdefinition^.options and (poclassmethod or poconstructor))=0) then
Message(parser_e_only_class_methods_via_class_ref);
end;
varsym:
begin
if isclassref then
Message(parser_e_only_class_methods_via_class_ref);
if (sym^.properties and sp_static)<>0 then
begin
static_name:=lowercase(srsymtable^.name^)+'_'+sym^.name;
getsym(static_name,true);
disposetree(p1);
p1:=genloadnode(pvarsym(srsym),srsymtable);
end
else
p1:=gensubscriptnode(pvarsym(sym),p1);
pd:=pvarsym(sym)^.definition;
end;
propertysym:
begin
if isclassref then
Message(parser_e_only_class_methods_via_class_ref);
paras:=nil;
{ property parameters? }
if token=LECKKLAMMER then
@ -499,6 +455,9 @@ unit pexpr;
p1:=genmethodcallnode(pprocsym(
ppropertysym(sym)^.writeaccesssym),
ppropertysym(sym)^.writeaccesssym^.owner,p1);
{ we know the procedure to call, so
force the usage of that procedure }
p1^.procdefinition:=pprocdef(ppropertysym(sym)^.writeaccessdef);
p1^.left:=paras;
{ to be on the save side }
oldafterassignment:=afterassignment;
@ -556,12 +515,19 @@ unit pexpr;
p1:=genmethodcallnode(pprocsym(
ppropertysym(sym)^.readaccesssym),
ppropertysym(sym)^.readaccesssym^.owner,p1);
{ we know the procedure to call, so
force the usage of that procedure }
p1^.procdefinition:=pprocdef(ppropertysym(sym)^.writeaccessdef);
{ insert paras }
p1^.left:=paras;
{ if we should be delphi compatible }
{ then force type conversion }
if cs_delphi2_compatible in aktswitches then
{ isn't neccessary, the result types }
{ have to match excatly }
{if cs_delphi2_compatible in aktswitches then
p1:=gentypeconvnode(p1,pd);
}
end
else
begin
@ -577,6 +543,62 @@ unit pexpr;
end;
end;
end;
{ the ID token has to be consumed before calling this function }
procedure do_member_read(const sym : psym;var p1 : ptree;
var pd : pdef;var again : boolean);
var
static_name : string;
isclassref : boolean;
begin
if sym=nil then
begin
Message(sym_e_id_no_member);
disposetree(p1);
p1:=genzeronode(errorn);
{ try to clean up }
pd:=generrordef;
again:=false;
end
else
begin
isclassref:=pd^.deftype=classrefdef;
{ we assume, that only procsyms and varsyms are in an object }
{ symbol table, for classes, properties are allowed }
case sym^.typ of
procsym:
begin
p1:=genmethodcallnode(pprocsym(sym),srsymtable,p1);
do_proc_call(false,again,p1,pd);
{ now we know the real method e.g. we can check for }
{ a class method }
if isclassref and ((p1^.procdefinition^.options and (poclassmethod or poconstructor))=0) then
Message(parser_e_only_class_methods_via_class_ref);
end;
varsym:
begin
if isclassref then
Message(parser_e_only_class_methods_via_class_ref);
if (sym^.properties and sp_static)<>0 then
begin
static_name:=lowercase(srsymtable^.name^)+'_'+sym^.name;
getsym(static_name,true);
disposetree(p1);
p1:=genloadnode(pvarsym(srsym),srsymtable);
end
else
p1:=gensubscriptnode(pvarsym(sym),p1);
pd:=pvarsym(sym)^.definition;
end;
propertysym:
begin
if isclassref then
Message(parser_e_only_class_methods_via_class_ref);
handle_propertysym(sym,p1,pd);
end;
else internalerror(16);
end;
end;
@ -595,6 +617,7 @@ unit pexpr;
classh : pobjectdef;
d : bestreal;
constset : pconstset;
propsym : ppropertysym;
{ p1 and p2 must contain valid values }
@ -621,7 +644,27 @@ unit pexpr;
pd:=ppointerdef(pd)^.definition;
end;
end;
LECKKLAMMER : begin
LECKKLAMMER:
begin
if (pd^.deftype=objectdef) and
pobjectdef(pd)^.isclass then
begin
{ default property }
propsym:=search_default_property(pobjectdef(pd));
if not(assigned(propsym)) then
begin
disposetree(p1);
p1:=genzeronode(errorn);
again:=false;
end
else
begin
p1:=nil;
handle_propertysym(propsym,p1,pd);
end;
end
else
begin
consume(LECKKLAMMER);
repeat
if (pd^.deftype<>arraydef) and
@ -631,6 +674,7 @@ unit pexpr;
Message(cg_e_invalid_qualifier);
disposetree(p1);
p1:=genzeronode(errorn);
again:=false;
end
else if (pd^.deftype=pointerdef) then
begin
@ -693,7 +737,9 @@ unit pexpr;
until false;
consume(RECKKLAMMER);
end;
POINT : begin
end;
POINT:
begin
consume(POINT);
case pd^.deftype of
recorddef:
@ -1049,7 +1095,9 @@ unit pexpr;
assigned(aktprocsym) and
((aktprocsym^.definition^.options and poclassmethod)<>0) then
Message(parser_e_only_class_methods);
{ !!!!! }
{ no method pointer }
p1:=nil;
handle_propertysym(srsym,p1,pd);
end;
errorsym:
begin
@ -1577,7 +1625,11 @@ unit pexpr;
end.
{
$Log$
Revision 1.5 1998-04-08 10:26:09 florian
Revision 1.6 1998-04-09 22:16:35 florian
* problem with previous REGALLOC solved
* improved property support
Revision 1.5 1998/04/08 10:26:09 florian
* correct error handling of virtual constructors
* problem with new type declaration handling fixed

View File

@ -204,11 +204,12 @@ unit tgeni386;
begin
if not(r in [R_EAX,R_EBX,R_ECX,R_EDX]) then
exit;
unused:=unused+[r];
inc(usablereg32);
end;
{$ifdef REGALLOC}
exprasmlist^.concat(new(pairegdealloc,init(r)));
{$endif REGALLOC}
inc(usablereg32);
end;
end;
{$ifdef SUPPORT_MMX}
@ -600,7 +601,11 @@ begin
end.
{
$Log$
Revision 1.2 1998-04-09 15:46:39 florian
Revision 1.3 1998-04-09 22:16:36 florian
* problem with previous REGALLOC solved
* improved property support
Revision 1.2 1998/04/09 15:46:39 florian
+ register allocation tracing stuff added
Revision 1.1.1.1 1998/03/25 11:18:15 root