* fixed pushing of records>8 bytes with stdcall

* simplified hightree loading
This commit is contained in:
peter 2002-12-17 22:19:33 +00:00
parent 107c954939
commit 46ed8eb932
7 changed files with 150 additions and 134 deletions

View File

@ -42,6 +42,7 @@ unit cpupara;
ti386paramanager = class(tparamanager) ti386paramanager = class(tparamanager)
function ret_in_acc(def : tdef;calloption : tproccalloption) : boolean;override; function ret_in_acc(def : tdef;calloption : tproccalloption) : boolean;override;
function ret_in_param(def : tdef;calloption : tproccalloption) : boolean;override; function ret_in_param(def : tdef;calloption : tproccalloption) : boolean;override;
function push_addr_param(def : tdef;calloption : tproccalloption) : boolean;override;
function getintparaloc(nr : longint) : tparalocation;override; function getintparaloc(nr : longint) : tparalocation;override;
procedure create_param_loc_info(p : tabstractprocdef);override; procedure create_param_loc_info(p : tabstractprocdef);override;
function getselflocation(p : tabstractprocdef) : tparalocation;override; function getselflocation(p : tabstractprocdef) : tparalocation;override;
@ -76,6 +77,16 @@ unit cpupara;
result:=inherited ret_in_param(def,calloption); result:=inherited ret_in_param(def,calloption);
end; end;
function ti386paramanager.push_addr_param(def : tdef;calloption : tproccalloption) : boolean;
begin
if ((target_info.system=system_i386_win32) and
(calloption=pocall_stdcall) and
(def.deftype=recorddef) and (def.size<=8)) then
result:=false
else
result:=inherited push_addr_param(def,calloption);
end;
function ti386paramanager.getintparaloc(nr : longint) : tparalocation; function ti386paramanager.getintparaloc(nr : longint) : tparalocation;
begin begin
end; end;
@ -100,7 +111,11 @@ begin
end. end.
{ {
$Log$ $Log$
Revision 1.5 2002-11-18 17:32:00 peter Revision 1.6 2002-12-17 22:19:33 peter
* fixed pushing of records>8 bytes with stdcall
* simplified hightree loading
Revision 1.5 2002/11/18 17:32:00 peter
* pass proccalloption to ret_in_xxx and push_xxx functions * pass proccalloption to ret_in_xxx and push_xxx functions
Revision 1.4 2002/11/15 01:58:56 peter Revision 1.4 2002/11/15 01:58:56 peter

View File

@ -567,9 +567,7 @@ implementation
is_array_of_const(left.resulttype.def) then is_array_of_const(left.resulttype.def) then
begin begin
{ Get high value } { Get high value }
srsym:=searchsymonlyin(tloadnode(left).symtable, hightree:=load_high_value(tvarsym(tloadnode(left).symtableentry));
'high'+tvarsym(tloadnode(left).symtableentry).name);
hightree:=cloadnode.create(tvarsym(srsym),tloadnode(left).symtable);
firstpass(hightree); firstpass(hightree);
secondpass(hightree); secondpass(hightree);
{ generate compares } { generate compares }
@ -921,7 +919,11 @@ begin
end. end.
{ {
$Log$ $Log$
Revision 1.37 2002-12-08 13:39:03 carl Revision 1.38 2002-12-17 22:19:33 peter
* fixed pushing of records>8 bytes with stdcall
* simplified hightree loading
Revision 1.37 2002/12/08 13:39:03 carl
+ some documentation added + some documentation added
Revision 1.36 2002/12/07 14:14:19 carl Revision 1.36 2002/12/07 14:14:19 carl

View File

@ -1096,7 +1096,8 @@ implementation
var var
vl,vl2 : TConstExprInt; vl,vl2 : TConstExprInt;
vr : bestreal; vr : bestreal;
hp,p1 : tnode; hightree,
hp : tnode;
srsym : tsym; srsym : tsym;
isreal : boolean; isreal : boolean;
checkrange : boolean; checkrange : boolean;
@ -1370,7 +1371,22 @@ implementation
in_sizeof_x: in_sizeof_x:
begin begin
set_varstate(left,false); set_varstate(left,false);
resulttype:=s32bittype; if paramanager.push_high_param(left.resulttype.def,aktprocdef.proccalloption) then
begin
hightree:=load_high_value(tvarsym(tloadnode(left).symtableentry));
if assigned(hightree) then
begin
hp:=caddnode.create(addn,hightree,
cordconstnode.create(1,s32bittype,false));
if (left.resulttype.def.deftype=arraydef) and
(tarraydef(left.resulttype.def).elesize<>1) then
hp:=caddnode.create(muln,hp,cordconstnode.create(tarraydef(
left.resulttype.def).elesize,s32bittype,true));
result:=hp;
end;
end
else
resulttype:=s32bittype;
end; end;
in_typeof_x: in_typeof_x:
@ -1519,15 +1535,13 @@ implementation
if is_open_array(left.resulttype.def) or if is_open_array(left.resulttype.def) or
is_array_of_const(left.resulttype.def) then is_array_of_const(left.resulttype.def) then
begin begin
srsym:=searchsymonlyin(tloadnode(left).symtable,'high'+tvarsym(tloadnode(left).symtableentry).name); hightree:=load_high_value(tvarsym(tloadnode(left).symtableentry));
if not assigned(srsym) then if assigned(hightree) then
begin begin
CGMessage(cg_e_illegal_expression); hp:=caddnode.create(addn,hightree,
goto myexit; cordconstnode.create(1,s32bittype,false));
result:=hp;
end; end;
hp:=caddnode.create(addn,cloadnode.create(srsym,tloadnode(left).symtable),
cordconstnode.create(1,s32bittype,false));
result:=hp;
goto myexit; goto myexit;
end end
else else
@ -1576,7 +1590,6 @@ implementation
{ is now nil } { is now nil }
left.free; left.free;
left := nil; left := nil;
resulttypepass(result);
goto myexit; goto myexit;
end; end;
@ -1685,6 +1698,7 @@ implementation
begin begin
result := handle_read_write; result := handle_read_write;
end; end;
in_settextbuf_file_x : in_settextbuf_file_x :
begin begin
resulttype:=voidtype; resulttype:=voidtype;
@ -1759,13 +1773,9 @@ implementation
else else
begin begin
if is_open_array(left.resulttype.def) or if is_open_array(left.resulttype.def) or
is_array_of_const(left.resulttype.def) then is_array_of_const(left.resulttype.def) then
begin begin
srsym:=searchsymonlyin(tloadnode(left).symtable,'high'+tvarsym(tloadnode(left).symtableentry).name); result:=load_high_value(tvarsym(tloadnode(left).symtableentry));
if assigned(srsym) then
result:=cloadnode.create(srsym,tloadnode(left).symtable)
else
CGMessage(cg_e_illegal_expression);
end end
else else
if is_dynamic_array(left.resulttype.def) then if is_dynamic_array(left.resulttype.def) then
@ -1786,32 +1796,19 @@ implementation
left.resulttype.def).highrange,tarraydef(left.resulttype.def).rangetype,true); left.resulttype.def).highrange,tarraydef(left.resulttype.def).rangetype,true);
end; end;
end; end;
if assigned(result) then
resulttypepass(result);
end; end;
stringdef: stringdef:
begin begin
if inlinenumber=in_low_x then if inlinenumber=in_low_x then
begin begin
hp:=cordconstnode.create(0,u8bittype,false); result:=cordconstnode.create(0,u8bittype,false);
resulttypepass(hp);
result:=hp;
end end
else else
begin begin
if is_open_string(left.resulttype.def) then if is_open_string(left.resulttype.def) then
begin result:=load_high_value(tvarsym(tloadnode(left).symtableentry))
srsym:=searchsymonlyin(tloadnode(left).symtable,'high'+tvarsym(tloadnode(left).symtableentry).name);
hp:=cloadnode.create(srsym,tloadnode(left).symtable);
resulttypepass(hp);
result:=hp;
end
else else
begin result:=cordconstnode.create(tstringdef(left.resulttype.def).len,u8bittype,true);
hp:=cordconstnode.create(tstringdef(left.resulttype.def).len,u8bittype,true);
resulttypepass(hp);
result:=hp;
end;
end; end;
end; end;
else else
@ -1951,6 +1948,14 @@ implementation
end end
else else
CGMessage(type_e_mismatch); CGMessage(type_e_mismatch);
{ We've checked the whole statement for correctness, now we
can remove it if assertions are off }
if not(cs_do_assertion in aktlocalswitches) then
begin
{ we need a valid node, so insert a nothingn }
result:=cnothingnode.create;
end;
end; end;
else else
@ -1972,7 +1977,6 @@ implementation
function tinlinenode.pass_1 : tnode; function tinlinenode.pass_1 : tnode;
var var
srsym : tsym;
hp,hpp : tnode; hp,hpp : tnode;
shiftconst: longint; shiftconst: longint;
@ -2018,26 +2022,12 @@ implementation
include(result.flags,nf_explizit); include(result.flags,nf_explizit);
firstpass(result); firstpass(result);
end; end;
in_sizeof_x: in_sizeof_x:
begin begin
if paramanager.push_high_param(left.resulttype.def,aktprocdef.proccalloption) then if registers32<1 then
begin registers32:=1;
srsym:=searchsymonlyin(tloadnode(left).symtable,'high'+tvarsym(tloadnode(left).symtableentry).name); location.loc:=LOC_REGISTER;
hp:=caddnode.create(addn,cloadnode.create(srsym,tloadnode(left).symtable),
cordconstnode.create(1,s32bittype,false));
if (left.resulttype.def.deftype=arraydef) and
(tarraydef(left.resulttype.def).elesize<>1) then
hp:=caddnode.create(muln,hp,cordconstnode.create(tarraydef(
left.resulttype.def).elesize,s32bittype,true));
firstpass(hp);
result:=hp;
end
else
begin
if registers32<1 then
registers32:=1;
location.loc:=LOC_REGISTER;
end;
end; end;
in_typeof_x: in_typeof_x:
@ -2260,22 +2250,11 @@ implementation
in_assert_x_y : in_assert_x_y :
begin begin
{ We've checked the whole statement for correctness, now we registers32:=left.registers32;
can remove it if assertions are off } registersfpu:=left.registersfpu;
if not(cs_do_assertion in aktlocalswitches) then
begin
{ we need a valid node, so insert a nothingn }
result:=cnothingnode.create;
firstpass(result);
end
else
begin
registers32:=left.registers32;
registersfpu:=left.registersfpu;
{$ifdef SUPPORT_MMX} {$ifdef SUPPORT_MMX}
registersmmx:=left.registersmmx; registersmmx:=left.registersmmx;
{$endif SUPPORT_MMX} {$endif SUPPORT_MMX}
end;
end; end;
else else
@ -2298,7 +2277,6 @@ implementation
function tinlinenode.first_pi : tnode; function tinlinenode.first_pi : tnode;
begin begin
result := crealconstnode.create(pi,pbestrealtype^); result := crealconstnode.create(pi,pbestrealtype^);
firstpass(result);
end; end;
@ -2308,10 +2286,6 @@ implementation
{ on entry left node contains the parameter } { on entry left node contains the parameter }
first_arctan_real := ccallnode.createintern('fpc_arctan_real', first_arctan_real := ccallnode.createintern('fpc_arctan_real',
ccallparanode.create(left,nil)); ccallparanode.create(left,nil));
{ now left is nil, nothing left, so no second pass
required.
}
firstpass(result);
left := nil; left := nil;
end; end;
@ -2321,10 +2295,6 @@ implementation
{ on entry left node contains the parameter } { on entry left node contains the parameter }
first_abs_real := ccallnode.createintern('fpc_abs_real', first_abs_real := ccallnode.createintern('fpc_abs_real',
ccallparanode.create(left,nil)); ccallparanode.create(left,nil));
{ now left is nil, nothing left, so no second pass
required.
}
firstpass(result);
left := nil; left := nil;
end; end;
@ -2334,10 +2304,6 @@ implementation
{ on entry left node contains the parameter } { on entry left node contains the parameter }
first_sqr_real := ccallnode.createintern('fpc_sqr_real', first_sqr_real := ccallnode.createintern('fpc_sqr_real',
ccallparanode.create(left,nil)); ccallparanode.create(left,nil));
{ now left is nil, nothing left, so no second pass
required.
}
firstpass(result);
left := nil; left := nil;
end; end;
@ -2347,10 +2313,6 @@ implementation
{ on entry left node contains the parameter } { on entry left node contains the parameter }
first_sqrt_real := ccallnode.createintern('fpc_sqrt_real', first_sqrt_real := ccallnode.createintern('fpc_sqrt_real',
ccallparanode.create(left,nil)); ccallparanode.create(left,nil));
{ now left is nil, nothing left, so no second pass
required.
}
firstpass(result);
left := nil; left := nil;
end; end;
@ -2360,10 +2322,6 @@ implementation
{ on entry left node contains the parameter } { on entry left node contains the parameter }
first_ln_real := ccallnode.createintern('fpc_ln_real', first_ln_real := ccallnode.createintern('fpc_ln_real',
ccallparanode.create(left,nil)); ccallparanode.create(left,nil));
{ now left is nil, nothing left, so no second pass
required.
}
firstpass(result);
left := nil; left := nil;
end; end;
@ -2373,10 +2331,6 @@ implementation
{ on entry left node contains the parameter } { on entry left node contains the parameter }
first_cos_real := ccallnode.createintern('fpc_cos_real', first_cos_real := ccallnode.createintern('fpc_cos_real',
ccallparanode.create(left,nil)); ccallparanode.create(left,nil));
{ now left is nil, nothing left, so no second pass
required.
}
firstpass(result);
left := nil; left := nil;
end; end;
@ -2386,10 +2340,6 @@ implementation
{ on entry left node contains the parameter } { on entry left node contains the parameter }
first_sin_real := ccallnode.createintern('fpc_sin_real', first_sin_real := ccallnode.createintern('fpc_sin_real',
ccallparanode.create(left,nil)); ccallparanode.create(left,nil));
{ now left is nil, nothing left, so no second pass
required.
}
firstpass(result);
left := nil; left := nil;
end; end;
@ -2399,7 +2349,11 @@ begin
end. end.
{ {
$Log$ $Log$
Revision 1.102 2002-12-15 21:30:12 florian Revision 1.103 2002-12-17 22:19:33 peter
* fixed pushing of records>8 bytes with stdcall
* simplified hightree loading
Revision 1.102 2002/12/15 21:30:12 florian
* tcallnode.paraitem introduced, all references to defcoll removed * tcallnode.paraitem introduced, all references to defcoll removed
Revision 1.101 2002/11/27 20:04:39 peter Revision 1.101 2002/11/27 20:04:39 peter

View File

@ -147,7 +147,9 @@ interface
crttinode : trttinodeclass; crttinode : trttinodeclass;
procedure load_procvar_from_calln(var p1:tnode); procedure load_procvar_from_calln(var p1:tnode);
function load_high_value(vs:tvarsym):tnode;
implementation implementation
@ -189,6 +191,27 @@ implementation
end; end;
function load_high_value(vs:tvarsym):tnode;
var
srsym : tsym;
srsymtable : tsymtable;
begin
srsymtable:=vs.owner;
if vo_is_local_copy in vs.varoptions then
begin
{ next symtable is always the para symtable }
srsymtable:=srsymtable.next;
if not(srsymtable.symtabletype in [parasymtable,inlineparasymtable]) then
internalerror(200212171);
end;
srsym:=searchsymonlyin(srsymtable,'high'+vs.name);
if assigned(srsym) then
result:=cloadnode.create(srsym,srsymtable)
else
CGMessage(cg_e_illegal_expression);
end;
{***************************************************************************** {*****************************************************************************
TLOADNODE TLOADNODE
*****************************************************************************} *****************************************************************************}
@ -695,8 +718,8 @@ implementation
{ check if the assignment may cause a range check error } { check if the assignment may cause a range check error }
{ if its not explicit, and only if the values are } { if its not explicit, and only if the values are }
{ ordinals, enumdef and floatdef } { ordinals, enumdef and floatdef }
if (right.nodetype = typeconvn) and if (right.nodetype = typeconvn) and
not (nf_explizit in ttypeconvnode(right).flags) then not (nf_explizit in ttypeconvnode(right).flags) then
begin begin
if assigned(left.resulttype.def) and if assigned(left.resulttype.def) and
@ -711,7 +734,7 @@ implementation
end; end;
end; end;
end; end;
{ call helpers for interface } { call helpers for interface }
if is_interfacecom(left.resulttype.def) then if is_interfacecom(left.resulttype.def) then
@ -1074,13 +1097,14 @@ implementation
exit; exit;
end; end;
end; end;
{ C Arguments are pushed on the stack and { Calculate registers }
are not accesible after the push } location.loc:=LOC_CREFERENCE;
if not(nf_cargs in flags) then
location.loc:=LOC_CREFERENCE
else
location.loc:=LOC_INVALID;
calcregisters(self,0,0,0); calcregisters(self,0,0,0);
{ C Arguments are pushed on the stack and
are not accesible after the push. This must be done
after calcregisters, because that needs a valid location }
if (nf_cargs in flags) then
location.loc:=LOC_INVALID;
end; end;
@ -1244,7 +1268,11 @@ begin
end. end.
{ {
$Log$ $Log$
Revision 1.71 2002-12-07 14:27:07 carl Revision 1.72 2002-12-17 22:19:33 peter
* fixed pushing of records>8 bytes with stdcall
* simplified hightree loading
Revision 1.71 2002/12/07 14:27:07 carl
* 3% memory optimization * 3% memory optimization
* changed some types * changed some types
+ added type checking with different size for call node and for + added type checking with different size for call node and for

View File

@ -193,7 +193,7 @@ unit paramgr;
end; end;
{ true if a parameter is too large to copy and only the address is pushed } { true if a parameter is too large to push and needs a concatcopy to get the value on the stack }
function tparamanager.copy_value_on_stack(def : tdef;calloption : tproccalloption) : boolean; function tparamanager.copy_value_on_stack(def : tdef;calloption : tproccalloption) : boolean;
begin begin
copy_value_on_stack:=false; copy_value_on_stack:=false;
@ -414,7 +414,11 @@ end.
{ {
$Log$ $Log$
Revision 1.27 2002-12-06 16:56:58 peter Revision 1.28 2002-12-17 22:19:33 peter
* fixed pushing of records>8 bytes with stdcall
* simplified hightree loading
Revision 1.27 2002/12/06 16:56:58 peter
* only compile cs_fp_emulation support when cpufpuemu is defined * only compile cs_fp_emulation support when cpufpuemu is defined
* define cpufpuemu for m68k only * define cpufpuemu for m68k only

View File

@ -162,6 +162,9 @@ implementation
if assigned(hp) then if assigned(hp) then
begin begin
p.free; p.free;
{ run firstpass }
firstpass(hp);
{ switch to new node }
p:=hp; p:=hp;
end; end;
if codegenerror then if codegenerror then
@ -205,7 +208,11 @@ implementation
end. end.
{ {
$Log$ $Log$
Revision 1.28 2002-09-05 19:28:30 peter Revision 1.29 2002-12-17 22:19:33 peter
* fixed pushing of records>8 bytes with stdcall
* simplified hightree loading
Revision 1.28 2002/09/05 19:28:30 peter
* removed repetitive pass counting * removed repetitive pass counting
* display heapsize also for extdebug * display heapsize also for extdebug

View File

@ -86,12 +86,22 @@ implementation
; ;
procedure resetvaluepara(p:tnamedindexitem;arg:pointer); procedure checkvaluepara(p:tnamedindexitem;arg:pointer);
begin begin
if tsym(p).typ=varsym then if tsym(p).typ<>varsym then
with tvarsym(p) do exit;
if copy(name,1,3)='val' then with tvarsym(p) do
aktprocdef.parast.symsearch.rename(name,copy(name,4,length(name))); begin
{ do we need a local copy? Then rename the varsym, do this after the
insert so the dup id checking is done correctly.
array of const and open array do not need this, the local copy routine
will patch the pushed value to point to the local copy }
if (varspez=vs_value) and
paramanager.push_addr_param(vartype.def,aktprocdef.proccalloption) and
not(is_array_of_const(vartype.def) or
is_open_array(vartype.def)) then
aktprocdef.parast.symsearch.rename(name,'val'+name);
end;
end; end;
@ -353,13 +363,6 @@ implementation
paramanager.push_addr_param(tt.def,aktprocdef.proccalloption) then paramanager.push_addr_param(tt.def,aktprocdef.proccalloption) then
include(vs.varoptions,vo_regable); include(vs.varoptions,vo_regable);
{ do we need a local copy? Then rename the varsym, do this after the
insert so the dup id checking is done correctly }
if (varspez=vs_value) and
paramanager.push_addr_param(tt.def,aktprocdef.proccalloption) and
not(is_open_array(tt.def) or is_array_of_const(tt.def)) then
currparast.rename(vs.name,'val'+vs.name);
{ also need to push a high value? } { also need to push a high value? }
if inserthigh then if inserthigh then
begin begin
@ -1548,9 +1551,13 @@ const
procedure handle_calling_convention(sym:tprocsym;def:tabstractprocdef); procedure handle_calling_convention(sym:tprocsym;def:tabstractprocdef);
begin begin
{ set the default calling convention } { set the default calling convention }
if def.proccalloption=pocall_none then if def.proccalloption=pocall_none then
def.proccalloption:=aktdefproccall; def.proccalloption:=aktdefproccall;
{ generate symbol names for local copies }
if (def.deftype=procdef) then
tprocdef(def).parast.foreach_static({$ifdef FPCPROCVAR}@{$endif}checkvaluepara,nil);
{ handle proccall specific settings }
case def.proccalloption of case def.proccalloption of
pocall_cdecl : pocall_cdecl :
begin begin
@ -1569,8 +1576,6 @@ const
end; end;
if not assigned(tprocdef(def).parast) then if not assigned(tprocdef(def).parast) then
internalerror(200110234); internalerror(200110234);
{ do not copy on local !! }
tprocdef(def).parast.foreach_static({$ifdef FPCPROCVAR}@{$endif}resetvaluepara,nil);
{ check C cdecl para types } { check C cdecl para types }
tprocdef(def).parast.foreach_static({$ifdef FPCPROCVAR}@{$endif}checkparatype,nil); tprocdef(def).parast.foreach_static({$ifdef FPCPROCVAR}@{$endif}checkparatype,nil);
{ Adjust alignment to match cdecl or stdcall } { Adjust alignment to match cdecl or stdcall }
@ -1591,8 +1596,6 @@ const
tprocdef(def).setmangledname(target_info.Cprefix+tprocdef(def).cplusplusmangledname); tprocdef(def).setmangledname(target_info.Cprefix+tprocdef(def).cplusplusmangledname);
if not assigned(tprocdef(def).parast) then if not assigned(tprocdef(def).parast) then
internalerror(200110235); internalerror(200110235);
{ do not copy on local !! }
tprocdef(def).parast.foreach_static({$ifdef FPCPROCVAR}@{$endif}resetvaluepara,nil);
{ check C cdecl para types } { check C cdecl para types }
tprocdef(def).parast.foreach_static({$ifdef FPCPROCVAR}@{$endif}checkparatype,nil); tprocdef(def).parast.foreach_static({$ifdef FPCPROCVAR}@{$endif}checkparatype,nil);
{ Adjust alignment to match cdecl or stdcall } { Adjust alignment to match cdecl or stdcall }
@ -1652,8 +1655,6 @@ const
begin begin
if not assigned(tprocdef(def).parast) then if not assigned(tprocdef(def).parast) then
internalerror(200110236); internalerror(200110236);
{ do not copy on local !! }
tprocdef(def).parast.foreach_static({$ifdef FPCPROCVAR}@{$endif}resetvaluepara,nil);
{ Adjust positions of args for cdecl or stdcall } { Adjust positions of args for cdecl or stdcall }
tprocdef(def).parast.dataalignment:=std_param_align; tprocdef(def).parast.dataalignment:=std_param_align;
end; end;
@ -1730,6 +1731,7 @@ const
end; end;
procedure parse_proc_directives(var pdflags:word); procedure parse_proc_directives(var pdflags:word);
{ {
Parse the procedure directives. It does not matter if procedure directives Parse the procedure directives. It does not matter if procedure directives
@ -2078,7 +2080,11 @@ const
end. end.
{ {
$Log$ $Log$
Revision 1.89 2002-12-15 21:07:30 peter Revision 1.90 2002-12-17 22:19:33 peter
* fixed pushing of records>8 bytes with stdcall
* simplified hightree loading
Revision 1.89 2002/12/15 21:07:30 peter
* don't allow external in object declarations * don't allow external in object declarations
Revision 1.88 2002/12/15 19:34:31 florian Revision 1.88 2002/12/15 19:34:31 florian