mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-17 22:49:23 +02:00
+ 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:
parent
c96538d24d
commit
694eee6cae
@ -90,6 +90,12 @@ interface
|
|||||||
|
|
||||||
ttempcreatenode = class;
|
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 }
|
{ 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 }
|
{ already been disposed and to make sure the coherency between temps and }
|
||||||
{ temp references is kept after a getcopy }
|
{ 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 }
|
{ 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 }
|
{ refs and deletenode can hook to this copy once they get copied too }
|
||||||
hookoncopy : ptempinfo;
|
hookoncopy : ptempinfo;
|
||||||
ref : treference;
|
|
||||||
restype : ttype;
|
restype : ttype;
|
||||||
temptype : ttemptype;
|
temptype : ttemptype;
|
||||||
|
owner : ttempcreatenode;
|
||||||
valid : boolean;
|
valid : boolean;
|
||||||
nextref_set_hookoncopy_nil : boolean;
|
nextref_set_hookoncopy_nil : boolean;
|
||||||
owner : ttempcreatenode;
|
loc : ttemplocation;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ a node which will create a (non)persistent temp of a given type with a given }
|
{ a node which will create a (non)persistent temp of a given type with a given }
|
||||||
@ -111,14 +117,16 @@ interface
|
|||||||
ttempcreatenode = class(tnode)
|
ttempcreatenode = class(tnode)
|
||||||
size: longint;
|
size: longint;
|
||||||
tempinfo: ptempinfo;
|
tempinfo: ptempinfo;
|
||||||
|
may_be_in_reg: boolean;
|
||||||
{ * persistent temps are used in manually written code where the temp }
|
{ * persistent temps are used in manually written code where the temp }
|
||||||
{ be usable among different statements and where you can manually say }
|
{ be usable among different statements and where you can manually say }
|
||||||
{ when the temp has to be freed (using a ttempdeletenode) }
|
{ when the temp has to be freed (using a ttempdeletenode) }
|
||||||
{ * non-persistent temps are mostly used in typeconversion helpers, }
|
{ * non-persistent temps are mostly used in typeconversion helpers, }
|
||||||
{ where the node that receives the temp becomes responsible for }
|
{ 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 }
|
{ to it and *not* generate a ttempdeletenode }
|
||||||
constructor create(const _restype: ttype; _size: longint; _temptype: ttemptype); virtual;
|
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;
|
constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
|
||||||
procedure ppuwrite(ppufile:tcompilerppufile);override;
|
procedure ppuwrite(ppufile:tcompilerppufile);override;
|
||||||
procedure buildderefimpl;override;
|
procedure buildderefimpl;override;
|
||||||
@ -660,6 +668,12 @@ implementation
|
|||||||
TEMPCREATENODE
|
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);
|
constructor ttempcreatenode.create(const _restype: ttype; _size: longint; _temptype: ttemptype);
|
||||||
begin
|
begin
|
||||||
inherited create(tempcreaten);
|
inherited create(tempcreaten);
|
||||||
@ -669,6 +683,7 @@ implementation
|
|||||||
tempinfo^.restype := _restype;
|
tempinfo^.restype := _restype;
|
||||||
tempinfo^.temptype := _temptype;
|
tempinfo^.temptype := _temptype;
|
||||||
tempinfo^.owner:=self;
|
tempinfo^.owner:=self;
|
||||||
|
may_be_in_reg:=false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function ttempcreatenode.getcopy: tnode;
|
function ttempcreatenode.getcopy: tnode;
|
||||||
@ -677,6 +692,7 @@ implementation
|
|||||||
begin
|
begin
|
||||||
n := ttempcreatenode(inherited getcopy);
|
n := ttempcreatenode(inherited getcopy);
|
||||||
n.size := size;
|
n.size := size;
|
||||||
|
n.may_be_in_reg := may_be_in_reg;
|
||||||
|
|
||||||
new(n.tempinfo);
|
new(n.tempinfo);
|
||||||
fillchar(n.tempinfo^,sizeof(n.tempinfo^),0);
|
fillchar(n.tempinfo^,sizeof(n.tempinfo^),0);
|
||||||
@ -704,6 +720,7 @@ implementation
|
|||||||
inherited ppuload(t,ppufile);
|
inherited ppuload(t,ppufile);
|
||||||
|
|
||||||
size:=ppufile.getlongint;
|
size:=ppufile.getlongint;
|
||||||
|
may_be_in_reg:=boolean(ppufile.getbyte);
|
||||||
new(tempinfo);
|
new(tempinfo);
|
||||||
fillchar(tempinfo^,sizeof(tempinfo^),0);
|
fillchar(tempinfo^,sizeof(tempinfo^),0);
|
||||||
ppufile.gettype(tempinfo^.restype);
|
ppufile.gettype(tempinfo^.restype);
|
||||||
@ -716,6 +733,7 @@ implementation
|
|||||||
begin
|
begin
|
||||||
inherited ppuwrite(ppufile);
|
inherited ppuwrite(ppufile);
|
||||||
ppufile.putlongint(size);
|
ppufile.putlongint(size);
|
||||||
|
ppufile.putbyte(byte(may_be_in_reg));
|
||||||
ppufile.puttype(tempinfo^.restype);
|
ppufile.puttype(tempinfo^.restype);
|
||||||
ppufile.putbyte(byte(tempinfo^.temptype));
|
ppufile.putbyte(byte(tempinfo^.temptype));
|
||||||
end;
|
end;
|
||||||
@ -751,6 +769,7 @@ implementation
|
|||||||
result :=
|
result :=
|
||||||
inherited docompare(p) and
|
inherited docompare(p) and
|
||||||
(ttempcreatenode(p).size = size) 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);
|
equal_defs(ttempcreatenode(p).tempinfo^.restype.def,tempinfo^.restype.def);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -983,7 +1002,15 @@ begin
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$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
|
* reginfo now also only allocated during register allocation
|
||||||
* third round of gdb cleanups: kick out most of concatstabto
|
* third round of gdb cleanups: kick out most of concatstabto
|
||||||
|
|
||||||
|
@ -337,6 +337,8 @@ interface
|
|||||||
*****************************************************************************}
|
*****************************************************************************}
|
||||||
|
|
||||||
procedure tcgtempcreatenode.pass_2;
|
procedure tcgtempcreatenode.pass_2;
|
||||||
|
var
|
||||||
|
cgsize: tcgsize;
|
||||||
begin
|
begin
|
||||||
location_reset(location,LOC_VOID,OS_NO);
|
location_reset(location,LOC_VOID,OS_NO);
|
||||||
|
|
||||||
@ -346,9 +348,37 @@ interface
|
|||||||
|
|
||||||
{ get a (persistent) temp }
|
{ get a (persistent) temp }
|
||||||
if tempinfo^.restype.def.needs_inittable then
|
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
|
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;
|
tempinfo^.valid := true;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -362,10 +392,26 @@ interface
|
|||||||
{ check if the temp is valid }
|
{ check if the temp is valid }
|
||||||
if not tempinfo^.valid then
|
if not tempinfo^.valid then
|
||||||
internalerror(200108231);
|
internalerror(200108231);
|
||||||
{ set the temp's location }
|
case tempinfo^.loc.loc of
|
||||||
location_reset(location,LOC_REFERENCE,def_cgsize(tempinfo^.restype.def));
|
LOC_REFERENCE:
|
||||||
location.reference := tempinfo^.ref;
|
begin
|
||||||
inc(location.reference.offset,offset);
|
{ 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;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -374,11 +420,13 @@ interface
|
|||||||
{ check if the temp is valid }
|
{ check if the temp is valid }
|
||||||
if not tempinfo^.valid then
|
if not tempinfo^.valid then
|
||||||
internalerror(200306081);
|
internalerror(200306081);
|
||||||
|
if (tempinfo^.loc.loc = LOC_REGISTER) then
|
||||||
|
internalerror(2004020203);
|
||||||
if (tempinfo^.temptype = tt_persistent) then
|
if (tempinfo^.temptype = tt_persistent) then
|
||||||
tg.ChangeTempType(exprasmlist,tempinfo^.ref,tt_normal);
|
tg.ChangeTempType(exprasmlist,tempinfo^.loc.ref,tt_normal);
|
||||||
tg.ungettemp(exprasmlist,tempinfo^.ref);
|
tg.ungettemp(exprasmlist,tempinfo^.loc.ref);
|
||||||
tempinfo^.ref := ref;
|
tempinfo^.loc.ref := ref;
|
||||||
tg.ChangeTempType(exprasmlist,tempinfo^.ref,tempinfo^.temptype);
|
tg.ChangeTempType(exprasmlist,tempinfo^.loc.ref,tempinfo^.temptype);
|
||||||
{ adapt location }
|
{ adapt location }
|
||||||
location.reference := ref;
|
location.reference := ref;
|
||||||
inc(location.reference.offset,offset);
|
inc(location.reference.offset,offset);
|
||||||
@ -393,10 +441,25 @@ interface
|
|||||||
begin
|
begin
|
||||||
location_reset(location,LOC_VOID,OS_NO);
|
location_reset(location,LOC_VOID,OS_NO);
|
||||||
|
|
||||||
if release_to_normal then
|
case tempinfo^.loc.loc of
|
||||||
tg.ChangeTempType(exprasmlist,tempinfo^.ref,tt_normal)
|
LOC_REFERENCE:
|
||||||
else
|
begin
|
||||||
tg.UnGetTemp(exprasmlist,tempinfo^.ref);
|
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;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -411,7 +474,15 @@ begin
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$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:
|
* Florian's culmutative nr. 1; contains:
|
||||||
- invalid calling conventions for a certain cpu are rejected
|
- invalid calling conventions for a certain cpu are rejected
|
||||||
- arm softfloat calling conventions
|
- arm softfloat calling conventions
|
||||||
|
@ -370,7 +370,7 @@ implementation
|
|||||||
|
|
||||||
{ since the input/output variables are threadvars loading them into
|
{ 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 }
|
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);
|
addstatement(newstatement,filetemp);
|
||||||
|
|
||||||
{ make sure the resulttype of the temp (and as such of the }
|
{ make sure the resulttype of the temp (and as such of the }
|
||||||
@ -2374,7 +2374,15 @@ begin
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$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
|
+ added prefetch(const mem) support
|
||||||
|
|
||||||
Revision 1.127 2004/01/26 16:12:28 daniel
|
Revision 1.127 2004/01/26 16:12:28 daniel
|
||||||
|
@ -240,7 +240,7 @@ implementation
|
|||||||
if is_new then
|
if is_new then
|
||||||
begin
|
begin
|
||||||
{ create temp for result }
|
{ 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);
|
addstatement(newstatement,temp);
|
||||||
|
|
||||||
{ create call to fpc_getmem }
|
{ create call to fpc_getmem }
|
||||||
@ -734,7 +734,15 @@ implementation
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$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)
|
* fixed allocation of dimension buffer for setlength(dynarr)
|
||||||
|
|
||||||
Revision 1.25 2003/11/29 16:19:54 peter
|
Revision 1.25 2003/11/29 16:19:54 peter
|
||||||
|
@ -436,7 +436,7 @@ implementation
|
|||||||
htype:=p.resulttype
|
htype:=p.resulttype
|
||||||
else
|
else
|
||||||
htype.setdef(tpointerdef.create(p.resulttype));
|
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);
|
resulttypepass(loadp);
|
||||||
if hasimplicitderef then
|
if hasimplicitderef then
|
||||||
begin
|
begin
|
||||||
@ -1087,7 +1087,15 @@ implementation
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$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
|
* except is also an end of block token
|
||||||
* after a label don't try to parse a statement when the next token
|
* after a label don't try to parse a statement when the next token
|
||||||
is an end token
|
is an end token
|
||||||
|
Loading…
Reference in New Issue
Block a user