diff --git a/compiler/nbas.pas b/compiler/nbas.pas index ccee66291d..6a69855de1 100644 --- a/compiler/nbas.pas +++ b/compiler/nbas.pas @@ -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 diff --git a/compiler/ncgbas.pas b/compiler/ncgbas.pas index 872127655a..e9ac3bc2b1 100644 --- a/compiler/ncgbas.pas +++ b/compiler/ncgbas.pas @@ -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 diff --git a/compiler/ninl.pas b/compiler/ninl.pas index 24aa698473..a2ea4359f4 100644 --- a/compiler/ninl.pas +++ b/compiler/ninl.pas @@ -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 diff --git a/compiler/pinline.pas b/compiler/pinline.pas index cb86da485e..8be198b27d 100644 --- a/compiler/pinline.pas +++ b/compiler/pinline.pas @@ -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 diff --git a/compiler/pstatmnt.pas b/compiler/pstatmnt.pas index e1fbe3cbd4..905aacdc6d 100644 --- a/compiler/pstatmnt.pas +++ b/compiler/pstatmnt.pas @@ -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