mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-13 18:24:19 +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;
|
||||
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user