|
@@ -94,6 +94,13 @@ interface
|
|
|
|
|
|
ttempcreatenode = class;
|
|
ttempcreatenode = class;
|
|
|
|
|
|
|
|
+ ttempinfoflag = (ti_may_be_in_reg,ti_valid,ti_nextref_set_hookoncopy_nil,ti_is_inlined_result);
|
|
|
|
+ ttempinfoflags = set of ttempinfoflag;
|
|
|
|
+
|
|
|
|
+const
|
|
|
|
+ tempinfostoreflags = [ti_may_be_in_reg,ti_is_inlined_result];
|
|
|
|
+
|
|
|
|
+type
|
|
{ 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 }
|
|
@@ -108,10 +115,7 @@ interface
|
|
owner : ttempcreatenode;
|
|
owner : ttempcreatenode;
|
|
withnode : tnode;
|
|
withnode : tnode;
|
|
location : tlocation;
|
|
location : tlocation;
|
|
- may_be_in_reg : boolean;
|
|
|
|
- valid : boolean;
|
|
|
|
- nextref_set_hookoncopy_nil : boolean;
|
|
|
|
- is_inlined_result : boolean;
|
|
|
|
|
|
+ flags : ttempinfoflags;
|
|
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 }
|
|
@@ -716,19 +720,19 @@ implementation
|
|
tempinfo^.temptype := _temptype;
|
|
tempinfo^.temptype := _temptype;
|
|
tempinfo^.owner := self;
|
|
tempinfo^.owner := self;
|
|
tempinfo^.withnode := nil;
|
|
tempinfo^.withnode := nil;
|
|
- tempinfo^.may_be_in_reg:=
|
|
|
|
- allowreg and
|
|
|
|
- { temp must fit a single register }
|
|
|
|
- (tstoreddef(_typedef).is_fpuregable or
|
|
|
|
- (tstoreddef(_typedef).is_intregable and
|
|
|
|
- (_size<=TCGSize2Size[OS_64]))) and
|
|
|
|
- { size of register operations must be known }
|
|
|
|
- (def_cgsize(_typedef)<>OS_NO) and
|
|
|
|
- { no init/final needed }
|
|
|
|
- not (_typedef.needs_inittable) and
|
|
|
|
- ((_typedef.typ <> pointerdef) or
|
|
|
|
- (is_object(tpointerdef(_typedef).pointeddef) or
|
|
|
|
- not tpointerdef(_typedef).pointeddef.needs_inittable));
|
|
|
|
|
|
+ if allowreg and
|
|
|
|
+ { temp must fit a single register }
|
|
|
|
+ (tstoreddef(_typedef).is_fpuregable or
|
|
|
|
+ (tstoreddef(_typedef).is_intregable and
|
|
|
|
+ (_size<=TCGSize2Size[OS_64]))) and
|
|
|
|
+ { size of register operations must be known }
|
|
|
|
+ (def_cgsize(_typedef)<>OS_NO) and
|
|
|
|
+ { no init/final needed }
|
|
|
|
+ not (_typedef.needs_inittable) and
|
|
|
|
+ ((_typedef.typ <> pointerdef) or
|
|
|
|
+ (is_object(tpointerdef(_typedef).pointeddef) or
|
|
|
|
+ not tpointerdef(_typedef).pointeddef.needs_inittable)) then
|
|
|
|
+ include(tempinfo^.flags,ti_may_be_in_reg);
|
|
end;
|
|
end;
|
|
|
|
|
|
constructor ttempcreatenode.create_withnode(_typedef: tdef; _size: aint; _temptype: ttemptype; allowreg:boolean; withnode: tnode);
|
|
constructor ttempcreatenode.create_withnode(_typedef: tdef; _size: aint; _temptype: ttemptype; allowreg:boolean; withnode: tnode);
|
|
@@ -741,7 +745,7 @@ implementation
|
|
constructor ttempcreatenode.create_inlined_result(_typedef: tdef; _size: aint; _temptype: ttemptype; allowreg:boolean);
|
|
constructor ttempcreatenode.create_inlined_result(_typedef: tdef; _size: aint; _temptype: ttemptype; allowreg:boolean);
|
|
begin
|
|
begin
|
|
self.create(_typedef,_size,_temptype,allowreg);
|
|
self.create(_typedef,_size,_temptype,allowreg);
|
|
- tempinfo^.is_inlined_result:=true;
|
|
|
|
|
|
+ include(tempinfo^.flags,ti_is_inlined_result);
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
@@ -757,8 +761,7 @@ implementation
|
|
n.tempinfo^.owner:=n;
|
|
n.tempinfo^.owner:=n;
|
|
n.tempinfo^.typedef := tempinfo^.typedef;
|
|
n.tempinfo^.typedef := tempinfo^.typedef;
|
|
n.tempinfo^.temptype := tempinfo^.temptype;
|
|
n.tempinfo^.temptype := tempinfo^.temptype;
|
|
- n.tempinfo^.may_be_in_reg := tempinfo^.may_be_in_reg;
|
|
|
|
- n.tempinfo^.is_inlined_result := tempinfo^.is_inlined_result;
|
|
|
|
|
|
+ n.tempinfo^.flags := tempinfo^.flags * tempinfostoreflags;
|
|
if assigned(tempinfo^.withnode) then
|
|
if assigned(tempinfo^.withnode) then
|
|
n.tempinfo^.withnode := tempinfo^.withnode.getcopy
|
|
n.tempinfo^.withnode := tempinfo^.withnode.getcopy
|
|
else
|
|
else
|
|
@@ -773,7 +776,7 @@ implementation
|
|
{ so that if the refs get copied as well, they can hook themselves }
|
|
{ so that if the refs get copied as well, they can hook themselves }
|
|
{ to the copy of the temp }
|
|
{ to the copy of the temp }
|
|
tempinfo^.hookoncopy := n.tempinfo;
|
|
tempinfo^.hookoncopy := n.tempinfo;
|
|
- tempinfo^.nextref_set_hookoncopy_nil := false;
|
|
|
|
|
|
+ exclude(tempinfo^.flags,ti_nextref_set_hookoncopy_nil);
|
|
|
|
|
|
result := n;
|
|
result := n;
|
|
end;
|
|
end;
|
|
@@ -786,8 +789,7 @@ implementation
|
|
size:=ppufile.getlongint;
|
|
size:=ppufile.getlongint;
|
|
new(tempinfo);
|
|
new(tempinfo);
|
|
fillchar(tempinfo^,sizeof(tempinfo^),0);
|
|
fillchar(tempinfo^,sizeof(tempinfo^),0);
|
|
- tempinfo^.may_be_in_reg:=boolean(ppufile.getbyte);
|
|
|
|
- tempinfo^.is_inlined_result:=boolean(ppufile.getbyte);
|
|
|
|
|
|
+ ppufile.getsmallset(tempinfo^.flags);
|
|
ppufile.getderef(tempinfo^.typedefderef);
|
|
ppufile.getderef(tempinfo^.typedefderef);
|
|
tempinfo^.temptype := ttemptype(ppufile.getbyte);
|
|
tempinfo^.temptype := ttemptype(ppufile.getbyte);
|
|
tempinfo^.owner:=self;
|
|
tempinfo^.owner:=self;
|
|
@@ -799,8 +801,7 @@ implementation
|
|
begin
|
|
begin
|
|
inherited ppuwrite(ppufile);
|
|
inherited ppuwrite(ppufile);
|
|
ppufile.putlongint(size);
|
|
ppufile.putlongint(size);
|
|
- ppufile.putbyte(byte(tempinfo^.may_be_in_reg));
|
|
|
|
- ppufile.putbyte(byte(tempinfo^.is_inlined_result));
|
|
|
|
|
|
+ ppufile.putsmallset(tempinfo^.flags);
|
|
ppufile.putderef(tempinfo^.typedefderef);
|
|
ppufile.putderef(tempinfo^.typedefderef);
|
|
ppufile.putbyte(byte(tempinfo^.temptype));
|
|
ppufile.putbyte(byte(tempinfo^.temptype));
|
|
ppuwritenode(ppufile,tempinfo^.withnode);
|
|
ppuwritenode(ppufile,tempinfo^.withnode);
|
|
@@ -859,8 +860,7 @@ implementation
|
|
result :=
|
|
result :=
|
|
inherited docompare(p) and
|
|
inherited docompare(p) and
|
|
(ttempcreatenode(p).size = size) and
|
|
(ttempcreatenode(p).size = size) and
|
|
- (ttempcreatenode(p).tempinfo^.may_be_in_reg = tempinfo^.may_be_in_reg) and
|
|
|
|
- (ttempcreatenode(p).tempinfo^.is_inlined_result = tempinfo^.is_inlined_result) and
|
|
|
|
|
|
+ (ttempcreatenode(p).tempinfo^.flags*tempinfostoreflags=tempinfo^.flags*tempinfostoreflags) and
|
|
(ttempcreatenode(p).tempinfo^.withnode.isequal(tempinfo^.withnode)) and
|
|
(ttempcreatenode(p).tempinfo^.withnode.isequal(tempinfo^.withnode)) and
|
|
equal_defs(ttempcreatenode(p).tempinfo^.typedef,tempinfo^.typedef);
|
|
equal_defs(ttempcreatenode(p).tempinfo^.typedef,tempinfo^.typedef);
|
|
end;
|
|
end;
|
|
@@ -909,7 +909,7 @@ implementation
|
|
{ from a persistent one into a normal one, we must be }
|
|
{ from a persistent one into a normal one, we must be }
|
|
{ the last reference (since our parent should free the }
|
|
{ the last reference (since our parent should free the }
|
|
{ temp (JM) }
|
|
{ temp (JM) }
|
|
- if (tempinfo^.nextref_set_hookoncopy_nil) then
|
|
|
|
|
|
+ if (ti_nextref_set_hookoncopy_nil in tempinfo^.flags) then
|
|
tempinfo^.hookoncopy := nil;
|
|
tempinfo^.hookoncopy := nil;
|
|
end
|
|
end
|
|
else
|
|
else
|
|
@@ -958,7 +958,7 @@ implementation
|
|
begin
|
|
begin
|
|
expectloc := LOC_REFERENCE;
|
|
expectloc := LOC_REFERENCE;
|
|
if not tempinfo^.typedef.needs_inittable and
|
|
if not tempinfo^.typedef.needs_inittable and
|
|
- tempinfo^.may_be_in_reg then
|
|
|
|
|
|
+ (ti_may_be_in_reg in tempinfo^.flags) then
|
|
begin
|
|
begin
|
|
if tempinfo^.typedef.typ=floatdef then
|
|
if tempinfo^.typedef.typ=floatdef then
|
|
begin
|
|
begin
|
|
@@ -1034,31 +1034,32 @@ implementation
|
|
var
|
|
var
|
|
n: ttempdeletenode;
|
|
n: ttempdeletenode;
|
|
begin
|
|
begin
|
|
- n := ttempdeletenode(inherited dogetcopy);
|
|
|
|
- n.release_to_normal := release_to_normal;
|
|
|
|
|
|
+ n:=ttempdeletenode(inherited dogetcopy);
|
|
|
|
+ n.release_to_normal:=release_to_normal;
|
|
|
|
|
|
if assigned(tempinfo^.hookoncopy) then
|
|
if assigned(tempinfo^.hookoncopy) then
|
|
{ if the temp has been copied, assume it becomes a new }
|
|
{ if the temp has been copied, assume it becomes a new }
|
|
{ temp which has to be hooked by the copied deletenode }
|
|
{ temp which has to be hooked by the copied deletenode }
|
|
begin
|
|
begin
|
|
{ hook the tempdeletenode to the copied temp }
|
|
{ hook the tempdeletenode to the copied temp }
|
|
- n.tempinfo := tempinfo^.hookoncopy;
|
|
|
|
|
|
+ n.tempinfo:=tempinfo^.hookoncopy;
|
|
{ the temp shall not be used, reset hookoncopy }
|
|
{ the temp shall not be used, reset hookoncopy }
|
|
{ Only if release_to_normal is false, otherwise }
|
|
{ Only if release_to_normal is false, otherwise }
|
|
{ the temp can still be referenced once more (JM) }
|
|
{ the temp can still be referenced once more (JM) }
|
|
if (not release_to_normal) then
|
|
if (not release_to_normal) then
|
|
tempinfo^.hookoncopy:=nil
|
|
tempinfo^.hookoncopy:=nil
|
|
else
|
|
else
|
|
- tempinfo^.nextref_set_hookoncopy_nil := true;
|
|
|
|
|
|
+ include(tempinfo^.flags,ti_nextref_set_hookoncopy_nil);
|
|
end
|
|
end
|
|
else
|
|
else
|
|
{ if the temp we refer to hasn't been copied, we have a }
|
|
{ if the temp we refer to hasn't been copied, we have a }
|
|
{ problem since that means we now have two delete nodes }
|
|
{ problem since that means we now have two delete nodes }
|
|
{ for one temp }
|
|
{ for one temp }
|
|
internalerror(200108234);
|
|
internalerror(200108234);
|
|
- result := n;
|
|
|
|
|
|
+ result:=n;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+
|
|
constructor ttempdeletenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
|
|
constructor ttempdeletenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
|
|
begin
|
|
begin
|
|
inherited ppuload(t,ppufile);
|
|
inherited ppuload(t,ppufile);
|