mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-02 09:09:47 +01:00
* support marking defs created via the getreusable*() class methods as
"don't free even if not registered"; use for defs that may not be written
to a ppu file, but that must nevertheless survive the compilation of the
current module
* mark all defs created for para locations as "don't free even if not
registered", because we don't discard and recalculate all para locations
after a module has been compiled (since that's not needed)
o solves issues if the paralocations for a routine in the interface of
unit A are calculated while the implementation of unit B gets
compiled, and a new reusable type is allocated at that point which
is not used anywhere else (after r32160)
git-svn-id: trunk@32235 -
This commit is contained in:
parent
d5aa498cf5
commit
fa3b0ca312
@ -318,7 +318,7 @@ unit cpupara;
|
||||
hp.paraloc[side].size:=OS_ADDR;
|
||||
hp.paraloc[side].alignment:=voidpointertype.alignment;
|
||||
hp.paraloc[side].intsize:=voidpointertype.size;
|
||||
hp.paraloc[side].def:=cpointerdef.getreusable(hp.vardef);
|
||||
hp.paraloc[side].def:=cpointerdef.getreusable_no_free(hp.vardef);
|
||||
with hp.paraloc[side].add_location^ do
|
||||
begin
|
||||
size:=OS_ADDR;
|
||||
@ -397,7 +397,7 @@ unit cpupara;
|
||||
|
||||
if push_addr_param(varspez,paradef,p.proccalloption) then
|
||||
begin
|
||||
paradef:=cpointerdef.getreusable(paradef);
|
||||
paradef:=cpointerdef.getreusable_no_free(paradef);
|
||||
loc:=LOC_REGISTER;
|
||||
paracgsize:=OS_ADDR;
|
||||
paralen:=tcgsize2size[OS_ADDR];
|
||||
|
||||
@ -92,7 +92,7 @@ unit cpupara;
|
||||
psym:=tparavarsym(pd.paras[nr-1]);
|
||||
pdef:=psym.vardef;
|
||||
if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
|
||||
pdef:=cpointerdef.getreusable(pdef);
|
||||
pdef:=cpointerdef.getreusable_no_free(pdef);
|
||||
cgpara.reset;
|
||||
cgpara.size:=def_cgsize(pdef);
|
||||
cgpara.intsize:=tcgsize2size[cgpara.size];
|
||||
@ -378,7 +378,7 @@ unit cpupara;
|
||||
|
||||
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
|
||||
begin
|
||||
paradef:=cpointerdef.getreusable(paradef);
|
||||
paradef:=cpointerdef.getreusable_no_free(paradef);
|
||||
loc:=LOC_REGISTER;
|
||||
paracgsize := OS_ADDR;
|
||||
paralen := tcgsize2size[OS_ADDR];
|
||||
@ -472,7 +472,7 @@ unit cpupara;
|
||||
{ LOC_REFERENCE always contains everything that's left }
|
||||
paraloc^.loc:=LOC_REFERENCE;
|
||||
paraloc^.size:=int_cgsize(paralen);
|
||||
paraloc^.def:=carraydef.getreusable(u8inttype,paralen);
|
||||
paraloc^.def:=carraydef.getreusable_no_free(u8inttype,paralen);
|
||||
if (side=callerside) then
|
||||
paraloc^.reference.index:=NR_STACK_POINTER_REG;
|
||||
paraloc^.reference.offset:=stack_offset;
|
||||
@ -546,7 +546,7 @@ unit cpupara;
|
||||
{ LOC_REFERENCE always contains everything that's left }
|
||||
paraloc^.loc:=LOC_REFERENCE;
|
||||
paraloc^.size:=int_cgsize(paralen);
|
||||
paraloc^.def:=carraydef.getreusable(u8inttype,paralen);
|
||||
paraloc^.def:=carraydef.getreusable_no_free(u8inttype,paralen);
|
||||
if (side=callerside) then
|
||||
paraloc^.reference.index:=NR_STACK_POINTER_REG;
|
||||
paraloc^.reference.offset:=stack_offset;
|
||||
@ -559,7 +559,7 @@ unit cpupara;
|
||||
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
|
||||
begin
|
||||
paraloc^.size:=OS_ADDR;
|
||||
paraloc^.def:=cpointerdef.getreusable(paradef);
|
||||
paraloc^.def:=cpointerdef.getreusable_no_free(paradef);
|
||||
assignintreg
|
||||
end
|
||||
else
|
||||
|
||||
@ -255,7 +255,7 @@ unit cpupara;
|
||||
|
||||
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
|
||||
begin
|
||||
paradef:=cpointerdef.getreusable(paradef);
|
||||
paradef:=cpointerdef.getreusable_no_free(paradef);
|
||||
loc:=LOC_REGISTER;
|
||||
paracgsize:=OS_ADDR;
|
||||
paralen:=tcgsize2size[OS_ADDR];
|
||||
@ -353,7 +353,7 @@ unit cpupara;
|
||||
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
|
||||
begin
|
||||
paraloc^.size:=OS_ADDR;
|
||||
paraloc^.def:=cpointerdef.getreusable(paradef);
|
||||
paraloc^.def:=cpointerdef.getreusable_no_free(paradef);
|
||||
assignintreg
|
||||
end
|
||||
else
|
||||
|
||||
@ -422,7 +422,7 @@ unit cpupara;
|
||||
begin
|
||||
paralen:=sizeof(aint);
|
||||
paracgsize:=OS_ADDR;
|
||||
paradef:=cpointerdef.getreusable(paradef);
|
||||
paradef:=cpointerdef.getreusable_no_free(paradef);
|
||||
end
|
||||
else
|
||||
begin
|
||||
@ -574,7 +574,7 @@ unit cpupara;
|
||||
begin
|
||||
paralen:=sizeof(aint);
|
||||
paracgsize:=OS_ADDR;
|
||||
paradef:=cpointerdef.getreusable(paradef);
|
||||
paradef:=cpointerdef.getreusable_no_free(paradef);
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
||||
@ -236,7 +236,7 @@ unit cpupara;
|
||||
psym:=tparavarsym(pd.paras[nr-1]);
|
||||
pdef:=psym.vardef;
|
||||
if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
|
||||
pdef:=cpointerdef.getreusable(pdef);
|
||||
pdef:=cpointerdef.getreusable_no_free(pdef);
|
||||
cgpara.reset;
|
||||
cgpara.size:=def_cgsize(pdef);
|
||||
cgpara.intsize:=tcgsize2size[cgpara.size];
|
||||
@ -442,7 +442,7 @@ unit cpupara;
|
||||
begin
|
||||
paralen:=voidpointertype.size;
|
||||
paracgsize:=int_cgsize(voidpointertype.size);
|
||||
paradef:=cpointerdef.getreusable(paradef);
|
||||
paradef:=cpointerdef.getreusable_no_free(paradef);
|
||||
end
|
||||
else
|
||||
begin
|
||||
@ -602,7 +602,7 @@ unit cpupara;
|
||||
begin
|
||||
paralen:=voidpointertype.size;
|
||||
paracgsize:=int_cgsize(voidpointertype.size);
|
||||
paradef:=cpointerdef.getreusable(paradef);
|
||||
paradef:=cpointerdef.getreusable_no_free(paradef);
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
||||
@ -160,7 +160,7 @@ implementation
|
||||
else if jvmimplicitpointertype(result.def) then
|
||||
begin
|
||||
retcgsize:=OS_ADDR;
|
||||
result.def:=cpointerdef.getreusable(result.def);
|
||||
result.def:=cpointerdef.getreusable_no_free(result.def);
|
||||
end
|
||||
else
|
||||
begin
|
||||
@ -237,7 +237,7 @@ implementation
|
||||
else if jvmimplicitpointertype(hp.vardef) then
|
||||
begin
|
||||
paracgsize:=OS_ADDR;
|
||||
paradef:=cpointerdef.getreusable(hp.vardef);
|
||||
paradef:=cpointerdef.getreusable_no_free(hp.vardef);
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
||||
@ -140,7 +140,7 @@ unit llvmpara;
|
||||
a pointer to the value that it should place on the stack (or
|
||||
passed in registers, in some cases) }
|
||||
paraloc^.llvmvalueloc:=false;
|
||||
paraloc^.def:=cpointerdef.getreusable(paraloc^.def);
|
||||
paraloc^.def:=cpointerdef.getreusable_no_free(paraloc^.def);
|
||||
paraloc^.size:=def_cgsize(paraloc^.def);
|
||||
paraloc^.loc:=LOC_REGISTER;
|
||||
paraloc^.register:=hlcg.getaddressregister(list,paraloc^.def);
|
||||
|
||||
@ -275,7 +275,7 @@ unit cpupara;
|
||||
|
||||
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
|
||||
begin
|
||||
paradef:=cpointerdef.getreusable(paradef);
|
||||
paradef:=cpointerdef.getreusable_no_free(paradef);
|
||||
paracgsize := OS_ADDR;
|
||||
paralen := tcgsize2size[OS_ADDR];
|
||||
end
|
||||
|
||||
@ -273,7 +273,7 @@ implementation
|
||||
begin
|
||||
paracgsize := OS_ADDR;
|
||||
paralen := tcgsize2size[paracgsize];
|
||||
paradef := cpointerdef.getreusable(paradef);
|
||||
paradef := cpointerdef.getreusable_no_free(paradef);
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
||||
@ -560,7 +560,7 @@ implementation
|
||||
retloc.def:=tdef(p.owner.defowner);
|
||||
if not (is_implicit_pointer_object_type(retloc.def) or
|
||||
(retloc.def.typ<>objectdef)) then
|
||||
retloc.def:=cpointerdef.getreusable(retloc.def);
|
||||
retloc.def:=cpointerdef.getreusable_no_free(retloc.def);
|
||||
end;
|
||||
retcgsize:=def_cgsize(retloc.def);
|
||||
retloc.intsize:=retloc.def.size;
|
||||
@ -568,7 +568,7 @@ implementation
|
||||
{ Return is passed as var parameter }
|
||||
if ret_in_param(retloc.def,p) then
|
||||
begin
|
||||
retloc.def:=cpointerdef.getreusable(retloc.def);
|
||||
retloc.def:=cpointerdef.getreusable_no_free(retloc.def);
|
||||
paraloc:=retloc.add_location;
|
||||
paraloc^.loc:=LOC_REFERENCE;
|
||||
paraloc^.size:=retcgsize;
|
||||
@ -621,7 +621,7 @@ implementation
|
||||
else if restlen in [1,2,4,8] then
|
||||
result:=cgsize_orddef(int_cgsize(restlen))
|
||||
else
|
||||
result:=carraydef.getreusable(u8inttype,restlen);
|
||||
result:=carraydef.getreusable_no_free(u8inttype,restlen);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
@ -568,7 +568,8 @@ implementation
|
||||
begin
|
||||
def:=tdef(current_module.localsymtable.deflist[i]);
|
||||
{ this also frees def, as the defs are owned by the symtable }
|
||||
if not def.is_registered then
|
||||
if not def.is_registered and
|
||||
not(df_not_registered_no_free in def.defoptions) then
|
||||
current_module.localsymtable.deletedef(def);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -87,7 +87,7 @@ unit cpupara;
|
||||
psym:=tparavarsym(pd.paras[nr-1]);
|
||||
pdef:=psym.vardef;
|
||||
if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
|
||||
pdef:=cpointerdef.getreusable(pdef);
|
||||
pdef:=cpointerdef.getreusable_no_free(pdef);
|
||||
cgpara.reset;
|
||||
cgpara.size:=def_cgsize(pdef);
|
||||
cgpara.intsize:=tcgsize2size[cgpara.size];
|
||||
@ -389,7 +389,7 @@ unit cpupara;
|
||||
|
||||
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
|
||||
begin
|
||||
paradef:=cpointerdef.getreusable(paradef);
|
||||
paradef:=cpointerdef.getreusable_no_free(paradef);
|
||||
loc:=LOC_REGISTER;
|
||||
paracgsize := OS_ADDR;
|
||||
paralen := tcgsize2size[OS_ADDR];
|
||||
@ -570,7 +570,7 @@ unit cpupara;
|
||||
if paraloc^.size<>OS_NO then
|
||||
paraloc^.def:=cgsize_orddef(paraloc^.size)
|
||||
else
|
||||
paraloc^.def:=carraydef.getreusable(u8inttype,paralen);
|
||||
paraloc^.def:=carraydef.getreusable_no_free(u8inttype,paralen);
|
||||
end;
|
||||
else
|
||||
internalerror(2006011101);
|
||||
|
||||
@ -88,7 +88,7 @@ begin
|
||||
psym:=tparavarsym(pd.paras[nr-1]);
|
||||
pdef:=psym.vardef;
|
||||
if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
|
||||
pdef:=cpointerdef.getreusable(pdef);
|
||||
pdef:=cpointerdef.getreusable_no_free(pdef);
|
||||
cgpara.reset;
|
||||
cgpara.size := def_cgsize(pdef);
|
||||
cgpara.intsize := tcgsize2size[cgpara.size];
|
||||
@ -418,7 +418,7 @@ begin
|
||||
next 8 byte boundary? }
|
||||
paraaligned:=false;
|
||||
if push_addr_param(varspez, paradef, p.proccalloption) then begin
|
||||
paradef := cpointerdef.getreusable(paradef);
|
||||
paradef := cpointerdef.getreusable_no_free(paradef);
|
||||
loc := LOC_REGISTER;
|
||||
paracgsize := OS_ADDR;
|
||||
paralen := tcgsize2size[OS_ADDR];
|
||||
|
||||
@ -196,7 +196,7 @@ implementation
|
||||
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
|
||||
begin
|
||||
paracgsize:=OS_ADDR;
|
||||
paradef:=cpointerdef.getreusable(paradef);
|
||||
paradef:=cpointerdef.getreusable_no_free(paradef);
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
||||
@ -212,7 +212,13 @@ type
|
||||
{ def has been copied from another def so symtable is not owned }
|
||||
df_copied_def,
|
||||
{ def was created as a generic constraint and thus is only "shallow" }
|
||||
df_genconstraint
|
||||
df_genconstraint,
|
||||
{ don't free def after finishing the implementation section even if it
|
||||
wasn't written to the ppu, as this def may still be referred (e.g. because
|
||||
it was used to set the type of a paraloc, since paralocs are reused
|
||||
across units) -- never stored to ppu, because in that case the def would
|
||||
be registered }
|
||||
df_not_registered_no_free
|
||||
);
|
||||
tdefoptions=set of tdefoption;
|
||||
|
||||
|
||||
@ -225,6 +225,11 @@ interface
|
||||
{ returns a pointerdef for def, reusing an existing one in case it
|
||||
exists in the current module }
|
||||
class function getreusable(def: tdef): tpointerdef; virtual;
|
||||
{ same as above, but in case the def must never be freed after the
|
||||
current module has been compiled -- even if the def was not written
|
||||
to the ppu file (for defs in para locations, as we don't reset them
|
||||
so we don't have to recalculate them all the time) }
|
||||
class function getreusable_no_free(def: tdef): tpointerdef;
|
||||
function size:asizeint;override;
|
||||
function getcopy:tstoreddef;override;
|
||||
constructor ppuload(ppufile:tcompilerppufile);
|
||||
@ -496,6 +501,11 @@ interface
|
||||
constructor create_from_pointer(def:tpointerdef);virtual;
|
||||
constructor create(l,h:asizeint;def:tdef);virtual;
|
||||
class function getreusable(def: tdef; elems: asizeint): tarraydef; virtual;
|
||||
{ same as above, but in case the def must never be freed after the
|
||||
current module has been compiled -- even if the def was not written
|
||||
to the ppu file (for defs in para locations, as we don't reset them
|
||||
so we don't have to recalculate them all the time) }
|
||||
class function getreusable_no_free(def: tdef; elems: asizeint): tarraydef;
|
||||
constructor ppuload(ppufile:tcompilerppufile);
|
||||
destructor destroy; override;
|
||||
function getcopy : tstoreddef;override;
|
||||
@ -616,6 +626,11 @@ interface
|
||||
constructor create(level:byte);virtual;
|
||||
{ returns a procvardef that represents the address of a proc(var)def }
|
||||
class function getreusableprocaddr(def: tabstractprocdef): tprocvardef; virtual;
|
||||
{ same as above, but in case the def must never be freed after the
|
||||
current module has been compiled -- even if the def was not written
|
||||
to the ppu file (for defs in para locations, as we don't reset them
|
||||
so we don't have to recalculate them all the time) }
|
||||
class function getreusableprocaddr_no_free(def: tabstractprocdef): tprocvardef;
|
||||
constructor ppuload(ppufile:tcompilerppufile);
|
||||
function getcopy : tstoreddef;override;
|
||||
{ do not override this routine in platform-specific subclasses,
|
||||
@ -2154,6 +2169,7 @@ implementation
|
||||
{ Register in current_module }
|
||||
if assigned(current_module) then
|
||||
begin
|
||||
exclude(defoptions,df_not_registered_no_free);
|
||||
if defid<defid_not_registered then
|
||||
defid:=deflist_index
|
||||
else
|
||||
@ -3224,6 +3240,14 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
class function tpointerdef.getreusable_no_free(def: tdef): tpointerdef;
|
||||
begin
|
||||
result:=getreusable(def);
|
||||
if not result.is_registered then
|
||||
include(result.defoptions,df_not_registered_no_free);
|
||||
end;
|
||||
|
||||
|
||||
function tpointerdef.size: asizeint;
|
||||
begin
|
||||
result:=sizeof(pint);
|
||||
@ -3540,6 +3564,13 @@ implementation
|
||||
result:=tarraydef(res^.Data);
|
||||
end;
|
||||
|
||||
class function tarraydef.getreusable_no_free(def: tdef; elems: asizeint): tarraydef;
|
||||
begin
|
||||
result:=getreusable(def,elems);
|
||||
if not result.is_registered then
|
||||
include(result.defoptions,df_not_registered_no_free);
|
||||
end;
|
||||
|
||||
|
||||
destructor tarraydef.destroy;
|
||||
begin
|
||||
@ -6086,6 +6117,14 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
class function tprocvardef.getreusableprocaddr_no_free(def: tabstractprocdef): tprocvardef;
|
||||
begin
|
||||
result:=getreusableprocaddr(def);
|
||||
if not result.is_registered then
|
||||
include(result.defoptions,df_not_registered_no_free);
|
||||
end;
|
||||
|
||||
|
||||
constructor tprocvardef.ppuload(ppufile:tcompilerppufile);
|
||||
begin
|
||||
inherited ppuload(procvardef,ppufile);
|
||||
|
||||
@ -1420,7 +1420,9 @@ const
|
||||
(mask:df_generic; str:'Generic'),
|
||||
(mask:df_specialization; str:'Specialization'),
|
||||
(mask:df_copied_def; str:'Copied Typedef'),
|
||||
(mask:df_genconstraint; str:'Generic Constraint')
|
||||
(mask:df_genconstraint; str:'Generic Constraint'),
|
||||
{ this should never happen for defs stored to a ppu file }
|
||||
(mask:df_not_registered_no_free; str:'Unregistered/No free (invalid)')
|
||||
);
|
||||
defstate : array[1..ord(high(tdefstate))] of tdefstateinfo=(
|
||||
(mask:ds_vmt_written; str:'VMT Written'),
|
||||
|
||||
@ -288,7 +288,7 @@ unit cpupara;
|
||||
else
|
||||
result:=class2;
|
||||
result.typ:=X86_64_SSE_CLASS;
|
||||
result.def:=carraydef.getreusable(s32floattype,2)
|
||||
result.def:=carraydef.getreusable_no_free(s32floattype,2)
|
||||
end;
|
||||
|
||||
|
||||
@ -401,7 +401,7 @@ unit cpupara;
|
||||
(classes[i-1].typ<>X86_64_SSEUP_CLASS) then
|
||||
begin
|
||||
classes[i].typ:=X86_64_SSE_CLASS;
|
||||
classes[i].def:=carraydef.getreusable(s32floattype,2);
|
||||
classes[i].def:=carraydef.getreusable_no_free(s32floattype,2);
|
||||
end;
|
||||
|
||||
(* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
|
||||
@ -443,7 +443,7 @@ unit cpupara;
|
||||
X86_64_SSESF_CLASS:
|
||||
begin
|
||||
classes[0].typ:=X86_64_SSE_CLASS;
|
||||
classes[0].def:=carraydef.getreusable(s32floattype,2);
|
||||
classes[0].def:=carraydef.getreusable_no_free(s32floattype,2);
|
||||
end;
|
||||
end;
|
||||
{ 2) the second part is 32 bit, but the total size is > 12 bytes }
|
||||
@ -457,7 +457,7 @@ unit cpupara;
|
||||
X86_64_SSESF_CLASS:
|
||||
begin
|
||||
classes[1].typ:=X86_64_SSE_CLASS;
|
||||
classes[1].def:=carraydef.getreusable(s32floattype,2);
|
||||
classes[1].def:=carraydef.getreusable_no_free(s32floattype,2);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -613,7 +613,7 @@ unit cpupara;
|
||||
{ if we have e.g. a record with two successive "single"
|
||||
fields, we need a 64 bit rather than a 32 bit load }
|
||||
classes[0].typ:=X86_64_SSE_CLASS;
|
||||
classes[0].def:=carraydef.getreusable(s32floattype,2);
|
||||
classes[0].def:=carraydef.getreusable_no_free(s32floattype,2);
|
||||
end;
|
||||
result:=1;
|
||||
end;
|
||||
@ -639,9 +639,9 @@ unit cpupara;
|
||||
s128real:
|
||||
begin
|
||||
classes[0].typ:=X86_64_SSE_CLASS;
|
||||
classes[0].def:=carraydef.getreusable(s32floattype,2);
|
||||
classes[0].def:=carraydef.getreusable_no_free(s32floattype,2);
|
||||
classes[1].typ:=X86_64_SSEUP_CLASS;
|
||||
classes[1].def:=carraydef.getreusable(s32floattype,2);
|
||||
classes[1].def:=carraydef.getreusable_no_free(s32floattype,2);
|
||||
result:=2;
|
||||
end;
|
||||
else
|
||||
@ -1102,7 +1102,7 @@ unit cpupara;
|
||||
loc[2].typ:=X86_64_NO_CLASS;
|
||||
paracgsize:=OS_ADDR;
|
||||
paralen:=sizeof(pint);
|
||||
paradef:=cpointerdef.getreusable(paradef);
|
||||
paradef:=cpointerdef.getreusable_no_free(paradef);
|
||||
loc[1].def:=paradef;
|
||||
end
|
||||
else
|
||||
|
||||
Loading…
Reference in New Issue
Block a user