+ support to store ttempcreate/ref/deletenodes in registers

* put temps for withnodes and some newnodes in registers
   Note: this currently only works because calling ungetregister()
     multiple times for the same register doesn't matter. We need again
     a way to specify that a register is currently a regvar and as such
     should not be freed when you call ungetregister() on it.
This commit is contained in:
Jonas Maebe 2004-02-03 16:46:51 +00:00
parent c96538d24d
commit 694eee6cae
5 changed files with 147 additions and 25 deletions

View File

@ -90,6 +90,12 @@ interface
ttempcreatenode = class;
ttemplocation = record
case loc: tcgloc of
LOC_REFERENCE: (ref: treference);
LOC_REGISTER: (reg: tregister);
end;
{ to allow access to the location by temp references even after the temp has }
{ already been disposed and to make sure the coherency between temps and }
{ temp references is kept after a getcopy }
@ -98,12 +104,12 @@ interface
{ set to the copy of a tempcreate pnode (if it gets copied) so that the }
{ refs and deletenode can hook to this copy once they get copied too }
hookoncopy : ptempinfo;
ref : treference;
restype : ttype;
temptype : ttemptype;
owner : ttempcreatenode;
valid : boolean;
nextref_set_hookoncopy_nil : boolean;
owner : ttempcreatenode;
loc : ttemplocation;
end;
{ a node which will create a (non)persistent temp of a given type with a given }
@ -111,14 +117,16 @@ interface
ttempcreatenode = class(tnode)
size: longint;
tempinfo: ptempinfo;
may_be_in_reg: boolean;
{ * persistent temps are used in manually written code where the temp }
{ be usable among different statements and where you can manually say }
{ when the temp has to be freed (using a ttempdeletenode) }
{ * non-persistent temps are mostly used in typeconversion helpers, }
{ where the node that receives the temp becomes responsible for }
{ freeing it. In this last case, you should use only one reference }
{ freeing it. In this last case, you must use only one reference }
{ to it and *not* generate a ttempdeletenode }
constructor create(const _restype: ttype; _size: longint; _temptype: ttemptype); virtual;
constructor create_reg(const _restype: ttype; _size: longint; _temptype: ttemptype); virtual;
constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
procedure ppuwrite(ppufile:tcompilerppufile);override;
procedure buildderefimpl;override;
@ -660,6 +668,12 @@ implementation
TEMPCREATENODE
*****************************************************************************}
constructor ttempcreatenode.create_reg(const _restype: ttype; _size: longint; _temptype: ttemptype);
begin
create(_restype,_size,_temptype);
may_be_in_reg:=true;
end;
constructor ttempcreatenode.create(const _restype: ttype; _size: longint; _temptype: ttemptype);
begin
inherited create(tempcreaten);
@ -669,6 +683,7 @@ implementation
tempinfo^.restype := _restype;
tempinfo^.temptype := _temptype;
tempinfo^.owner:=self;
may_be_in_reg:=false;
end;
function ttempcreatenode.getcopy: tnode;
@ -677,6 +692,7 @@ implementation
begin
n := ttempcreatenode(inherited getcopy);
n.size := size;
n.may_be_in_reg := may_be_in_reg;
new(n.tempinfo);
fillchar(n.tempinfo^,sizeof(n.tempinfo^),0);
@ -704,6 +720,7 @@ implementation
inherited ppuload(t,ppufile);
size:=ppufile.getlongint;
may_be_in_reg:=boolean(ppufile.getbyte);
new(tempinfo);
fillchar(tempinfo^,sizeof(tempinfo^),0);
ppufile.gettype(tempinfo^.restype);
@ -716,6 +733,7 @@ implementation
begin
inherited ppuwrite(ppufile);
ppufile.putlongint(size);
ppufile.putbyte(byte(may_be_in_reg));
ppufile.puttype(tempinfo^.restype);
ppufile.putbyte(byte(tempinfo^.temptype));
end;
@ -751,6 +769,7 @@ implementation
result :=
inherited docompare(p) and
(ttempcreatenode(p).size = size) and
(ttempcreatenode(p).may_be_in_reg = may_be_in_reg) and
equal_defs(ttempcreatenode(p).tempinfo^.restype.def,tempinfo^.restype.def);
end;
@ -983,7 +1002,15 @@ begin
end.
{
$Log$
Revision 1.75 2004-01-26 16:12:27 daniel
Revision 1.76 2004-02-03 16:46:51 jonas
+ support to store ttempcreate/ref/deletenodes in registers
* put temps for withnodes and some newnodes in registers
Note: this currently only works because calling ungetregister()
multiple times for the same register doesn't matter. We need again
a way to specify that a register is currently a regvar and as such
should not be freed when you call ungetregister() on it.
Revision 1.75 2004/01/26 16:12:27 daniel
* reginfo now also only allocated during register allocation
* third round of gdb cleanups: kick out most of concatstabto

View File

@ -337,6 +337,8 @@ interface
*****************************************************************************}
procedure tcgtempcreatenode.pass_2;
var
cgsize: tcgsize;
begin
location_reset(location,LOC_VOID,OS_NO);
@ -346,9 +348,37 @@ interface
{ get a (persistent) temp }
if tempinfo^.restype.def.needs_inittable then
tg.GetTempTyped(exprasmlist,tempinfo^.restype.def,tempinfo^.temptype,tempinfo^.ref)
begin
tg.GetTempTyped(exprasmlist,tempinfo^.restype.def,tempinfo^.temptype,tempinfo^.loc.ref);
tempinfo^.loc.loc := LOC_REFERENCE;
end
else if may_be_in_reg then
begin
cgsize := def_cgsize(tempinfo^.restype.def);
if (OS_INT = OS_S32) then
begin
if not(cgsize in [OS_8,OS_16,OS_32,OS_S8,OS_S16,OS_S32]) then
internalerror(2004020202);
end
else
begin
if not(cgsize in [OS_8,OS_16,OS_32,OS_64,OS_S8,OS_S16,OS_S32,OS_S64]) then
internalerror(2004020202);
end;
tempinfo^.loc.reg := cg.getintregister(exprasmlist,cgsize);
if (tempinfo^.temptype = tt_persistent) then
begin
{ !!tell rgobj this register is now a regvar, so it can't be freed!! }
tempinfo^.loc.loc := LOC_CREGISTER
end
else
tempinfo^.loc.loc := LOC_REGISTER;
end
else
tg.GetTemp(exprasmlist,size,tempinfo^.temptype,tempinfo^.ref);
begin
tg.GetTemp(exprasmlist,size,tempinfo^.temptype,tempinfo^.loc.ref);
tempinfo^.loc.loc := LOC_REFERENCE;
end;
tempinfo^.valid := true;
end;
@ -362,10 +392,26 @@ interface
{ check if the temp is valid }
if not tempinfo^.valid then
internalerror(200108231);
{ set the temp's location }
location_reset(location,LOC_REFERENCE,def_cgsize(tempinfo^.restype.def));
location.reference := tempinfo^.ref;
inc(location.reference.offset,offset);
case tempinfo^.loc.loc of
LOC_REFERENCE:
begin
{ set the temp's location }
location_reset(location,LOC_REFERENCE,def_cgsize(tempinfo^.restype.def));
location.reference := tempinfo^.loc.ref;
inc(location.reference.offset,offset);
end;
LOC_REGISTER,
LOC_CREGISTER:
begin
if offset <> 0 then
internalerror(2004020205);
{ LOC_CREGISTER, not LOC_REGISTER, otherwise we can't assign anything to it }
location_reset(location,tempinfo^.loc.loc,def_cgsize(tempinfo^.restype.def));
location.register := tempinfo^.loc.reg;
end;
else
internalerror(2004020204);
end;
end;
@ -374,11 +420,13 @@ interface
{ check if the temp is valid }
if not tempinfo^.valid then
internalerror(200306081);
if (tempinfo^.loc.loc = LOC_REGISTER) then
internalerror(2004020203);
if (tempinfo^.temptype = tt_persistent) then
tg.ChangeTempType(exprasmlist,tempinfo^.ref,tt_normal);
tg.ungettemp(exprasmlist,tempinfo^.ref);
tempinfo^.ref := ref;
tg.ChangeTempType(exprasmlist,tempinfo^.ref,tempinfo^.temptype);
tg.ChangeTempType(exprasmlist,tempinfo^.loc.ref,tt_normal);
tg.ungettemp(exprasmlist,tempinfo^.loc.ref);
tempinfo^.loc.ref := ref;
tg.ChangeTempType(exprasmlist,tempinfo^.loc.ref,tempinfo^.temptype);
{ adapt location }
location.reference := ref;
inc(location.reference.offset,offset);
@ -393,10 +441,25 @@ interface
begin
location_reset(location,LOC_VOID,OS_NO);
if release_to_normal then
tg.ChangeTempType(exprasmlist,tempinfo^.ref,tt_normal)
else
tg.UnGetTemp(exprasmlist,tempinfo^.ref);
case tempinfo^.loc.loc of
LOC_REFERENCE:
begin
if release_to_normal then
tg.ChangeTempType(exprasmlist,tempinfo^.loc.ref,tt_normal)
else
tg.UnGetTemp(exprasmlist,tempinfo^.loc.ref);
end;
LOC_REGISTER:
begin
if release_to_normal then
tempinfo^.loc.loc := LOC_REGISTER
else
begin
{ !!tell rgobj this register is no longer a regvar!! }
cg.ungetregister(exprasmlist,tempinfo^.loc.reg);
end;
end;
end;
end;
@ -411,7 +474,15 @@ begin
end.
{
$Log$
Revision 1.51 2003-11-07 15:58:32 florian
Revision 1.52 2004-02-03 16:46:51 jonas
+ support to store ttempcreate/ref/deletenodes in registers
* put temps for withnodes and some newnodes in registers
Note: this currently only works because calling ungetregister()
multiple times for the same register doesn't matter. We need again
a way to specify that a register is currently a regvar and as such
should not be freed when you call ungetregister() on it.
Revision 1.51 2003/11/07 15:58:32 florian
* Florian's culmutative nr. 1; contains:
- invalid calling conventions for a certain cpu are rejected
- arm softfloat calling conventions

View File

@ -370,7 +370,7 @@ implementation
{ since the input/output variables are threadvars loading them into
a temp once is faster. Create a temp which will hold a pointer to the file }
filetemp := ctempcreatenode.create(voidpointertype,voidpointertype.def.size,tt_persistent);
filetemp := ctempcreatenode.create_reg(voidpointertype,voidpointertype.def.size,tt_persistent);
addstatement(newstatement,filetemp);
{ make sure the resulttype of the temp (and as such of the }
@ -2374,7 +2374,15 @@ begin
end.
{
$Log$
Revision 1.128 2004-02-02 20:41:59 florian
Revision 1.129 2004-02-03 16:46:51 jonas
+ support to store ttempcreate/ref/deletenodes in registers
* put temps for withnodes and some newnodes in registers
Note: this currently only works because calling ungetregister()
multiple times for the same register doesn't matter. We need again
a way to specify that a register is currently a regvar and as such
should not be freed when you call ungetregister() on it.
Revision 1.128 2004/02/02 20:41:59 florian
+ added prefetch(const mem) support
Revision 1.127 2004/01/26 16:12:28 daniel

View File

@ -240,7 +240,7 @@ implementation
if is_new then
begin
{ create temp for result }
temp := ctempcreatenode.create(p.resulttype,p.resulttype.def.size,tt_persistent);
temp := ctempcreatenode.create_reg(p.resulttype,p.resulttype.def.size,tt_persistent);
addstatement(newstatement,temp);
{ create call to fpc_getmem }
@ -734,7 +734,15 @@ implementation
end.
{
$Log$
Revision 1.26 2004-01-22 16:44:35 peter
Revision 1.27 2004-02-03 16:46:51 jonas
+ support to store ttempcreate/ref/deletenodes in registers
* put temps for withnodes and some newnodes in registers
Note: this currently only works because calling ungetregister()
multiple times for the same register doesn't matter. We need again
a way to specify that a register is currently a regvar and as such
should not be freed when you call ungetregister() on it.
Revision 1.26 2004/01/22 16:44:35 peter
* fixed allocation of dimension buffer for setlength(dynarr)
Revision 1.25 2003/11/29 16:19:54 peter

View File

@ -436,7 +436,7 @@ implementation
htype:=p.resulttype
else
htype.setdef(tpointerdef.create(p.resulttype));
loadp:=ctempcreatenode.create(htype,POINTER_SIZE,tt_persistent);
loadp:=ctempcreatenode.create_reg(htype,POINTER_SIZE,tt_persistent);
resulttypepass(loadp);
if hasimplicitderef then
begin
@ -1087,7 +1087,15 @@ implementation
end.
{
$Log$
Revision 1.126 2004-01-22 17:24:49 peter
Revision 1.127 2004-02-03 16:46:51 jonas
+ support to store ttempcreate/ref/deletenodes in registers
* put temps for withnodes and some newnodes in registers
Note: this currently only works because calling ungetregister()
multiple times for the same register doesn't matter. We need again
a way to specify that a register is currently a regvar and as such
should not be freed when you call ungetregister() on it.
Revision 1.126 2004/01/22 17:24:49 peter
* except is also an end of block token
* after a label don't try to parse a statement when the next token
is an end token