mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-14 18:09:09 +02:00
+ support for nested procedures for the JVM target
o since the JVM target has no stack/framepointer that can be passed on to nested routines, all local variables and parameters accessed from nested routines are grouped into a local record whose address is passed to nested routines. The same technique is also required for LLVM in the future git-svn-id: branches/jvmbackend@18588 -
This commit is contained in:
parent
874095a1c0
commit
8fa42c206f
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -348,6 +348,8 @@ compiler/ncginl.pas svneol=native#text/plain
|
|||||||
compiler/ncgld.pas svneol=native#text/plain
|
compiler/ncgld.pas svneol=native#text/plain
|
||||||
compiler/ncgmat.pas svneol=native#text/plain
|
compiler/ncgmat.pas svneol=native#text/plain
|
||||||
compiler/ncgmem.pas svneol=native#text/plain
|
compiler/ncgmem.pas svneol=native#text/plain
|
||||||
|
compiler/ncgnstld.pas svneol=native#text/plain
|
||||||
|
compiler/ncgnstmm.pas svneol=native#text/plain
|
||||||
compiler/ncgobjc.pas svneol=native#text/plain
|
compiler/ncgobjc.pas svneol=native#text/plain
|
||||||
compiler/ncgopt.pas svneol=native#text/plain
|
compiler/ncgopt.pas svneol=native#text/plain
|
||||||
compiler/ncgrtti.pas svneol=native#text/plain
|
compiler/ncgrtti.pas svneol=native#text/plain
|
||||||
|
@ -29,10 +29,10 @@ uses
|
|||||||
globtype,
|
globtype,
|
||||||
symtype,
|
symtype,
|
||||||
cgutils,
|
cgutils,
|
||||||
node, ncgld;
|
node, ncgld, ncgnstld;
|
||||||
|
|
||||||
type
|
type
|
||||||
tjvmloadnode = class(tcgloadnode)
|
tjvmloadnode = class(tcgnestloadnode)
|
||||||
function is_addr_param_load: boolean; override;
|
function is_addr_param_load: boolean; override;
|
||||||
procedure pass_generate_code; override;
|
procedure pass_generate_code; override;
|
||||||
end;
|
end;
|
||||||
|
@ -28,7 +28,7 @@ interface
|
|||||||
uses
|
uses
|
||||||
globtype,
|
globtype,
|
||||||
cgbase,cpubase,
|
cgbase,cpubase,
|
||||||
node,nmem,ncgmem;
|
node,nmem,ncgmem,ncgnstmm;
|
||||||
|
|
||||||
type
|
type
|
||||||
tjvmaddrnode = class(tcgaddrnode)
|
tjvmaddrnode = class(tcgaddrnode)
|
||||||
@ -45,10 +45,6 @@ interface
|
|||||||
procedure pass_generate_code; override;
|
procedure pass_generate_code; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
tjvmloadparentfpnode = class(tcgloadparentfpnode)
|
|
||||||
procedure pass_generate_code;override;
|
|
||||||
end;
|
|
||||||
|
|
||||||
tjvmvecnode = class(tcgvecnode)
|
tjvmvecnode = class(tcgvecnode)
|
||||||
function pass_1: tnode; override;
|
function pass_1: tnode; override;
|
||||||
procedure pass_generate_code;override;
|
procedure pass_generate_code;override;
|
||||||
@ -121,7 +117,8 @@ implementation
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
if not jvmimplicitpointertype(left.resultdef) then
|
if not(nf_internal in flags) and
|
||||||
|
not jvmimplicitpointertype(left.resultdef) then
|
||||||
begin
|
begin
|
||||||
CGMessage(parser_e_illegal_expression);
|
CGMessage(parser_e_illegal_expression);
|
||||||
exit
|
exit
|
||||||
@ -134,7 +131,8 @@ implementation
|
|||||||
procedure tjvmaddrnode.pass_generate_code;
|
procedure tjvmaddrnode.pass_generate_code;
|
||||||
begin
|
begin
|
||||||
secondpass(left);
|
secondpass(left);
|
||||||
if jvmimplicitpointertype(left.resultdef) then
|
if jvmimplicitpointertype(left.resultdef) or
|
||||||
|
(nf_internal in flags) then
|
||||||
begin
|
begin
|
||||||
{ this is basically a typecast: the left node is an implicit
|
{ this is basically a typecast: the left node is an implicit
|
||||||
pointer, and we typecast it to a regular 'pointer'
|
pointer, and we typecast it to a regular 'pointer'
|
||||||
@ -143,6 +141,7 @@ implementation
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
{ procvar }
|
||||||
{$ifndef nounsupported}
|
{$ifndef nounsupported}
|
||||||
location_reset(location,LOC_REGISTER,OS_ADDR);
|
location_reset(location,LOC_REGISTER,OS_ADDR);
|
||||||
location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,java_jlobject);
|
location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,java_jlobject);
|
||||||
@ -168,19 +167,6 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ tjvmloadparentfpnode }
|
|
||||||
|
|
||||||
procedure tjvmloadparentfpnode.pass_generate_code;
|
|
||||||
begin
|
|
||||||
{$ifndef nounsupported}
|
|
||||||
location_reset(location,LOC_REGISTER,OS_ADDR);
|
|
||||||
location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,java_jlobject);
|
|
||||||
hlcg.a_load_const_reg(current_asmdata.CurrAsmList,java_jlobject,0,location.register);
|
|
||||||
{$else}
|
|
||||||
internalerror(2011041301);
|
|
||||||
{$endif}
|
|
||||||
end;
|
|
||||||
|
|
||||||
{*****************************************************************************
|
{*****************************************************************************
|
||||||
TJVMVECNODE
|
TJVMVECNODE
|
||||||
*****************************************************************************}
|
*****************************************************************************}
|
||||||
@ -298,6 +284,5 @@ begin
|
|||||||
cderefnode:=tjvmderefnode;
|
cderefnode:=tjvmderefnode;
|
||||||
caddrnode:=tjvmaddrnode;
|
caddrnode:=tjvmaddrnode;
|
||||||
cvecnode:=tjvmvecnode;
|
cvecnode:=tjvmvecnode;
|
||||||
cloadparentfpnode:=tjvmloadparentfpnode;
|
|
||||||
cloadvmtaddrnode:=tjvmloadvmtaddrnode;
|
cloadvmtaddrnode:=tjvmloadvmtaddrnode;
|
||||||
end.
|
end.
|
||||||
|
@ -241,7 +241,11 @@ implementation
|
|||||||
else if jvmimplicitpointertype(tpointerdef(def).pointeddef) then
|
else if jvmimplicitpointertype(tpointerdef(def).pointeddef) then
|
||||||
result:=jvmaddencodedtype(tpointerdef(def).pointeddef,false,encodedstr,forcesignature,founderror)
|
result:=jvmaddencodedtype(tpointerdef(def).pointeddef,false,encodedstr,forcesignature,founderror)
|
||||||
else
|
else
|
||||||
result:=false;
|
begin
|
||||||
|
{ used for internal pointer constructs }
|
||||||
|
encodedstr:=encodedstr+'[';
|
||||||
|
result:=jvmaddencodedtype(tpointerdef(def).pointeddef,false,encodedstr,forcesignature,founderror);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
floatdef :
|
floatdef :
|
||||||
begin
|
begin
|
||||||
|
@ -33,6 +33,9 @@ interface
|
|||||||
|
|
||||||
type
|
type
|
||||||
tcgloadnode = class(tloadnode)
|
tcgloadnode = class(tloadnode)
|
||||||
|
protected
|
||||||
|
procedure generate_nested_access(vs: tsym);virtual;
|
||||||
|
public
|
||||||
procedure pass_generate_code;override;
|
procedure pass_generate_code;override;
|
||||||
procedure generate_picvaraccess;virtual;
|
procedure generate_picvaraccess;virtual;
|
||||||
procedure changereflocation(const ref: treference);
|
procedure changereflocation(const ref: treference);
|
||||||
@ -235,6 +238,20 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure tcgloadnode.generate_nested_access(vs: tsym);
|
||||||
|
var
|
||||||
|
{ paramter declared as tsym to reduce interface unit dependencies }
|
||||||
|
lvs: tabstractnormalvarsym absolute vs;
|
||||||
|
begin
|
||||||
|
secondpass(left);
|
||||||
|
if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
|
||||||
|
internalerror(200309286);
|
||||||
|
if lvs.localloc.loc<>LOC_REFERENCE then
|
||||||
|
internalerror(200409241);
|
||||||
|
reference_reset_base(location.reference,left.location.register,lvs.localloc.reference.offset,lvs.localloc.reference.alignment);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure tcgloadnode.pass_generate_code;
|
procedure tcgloadnode.pass_generate_code;
|
||||||
var
|
var
|
||||||
hregister : tregister;
|
hregister : tregister;
|
||||||
@ -412,19 +429,10 @@ implementation
|
|||||||
localvarsym :
|
localvarsym :
|
||||||
begin
|
begin
|
||||||
vs:=tabstractnormalvarsym(symtableentry);
|
vs:=tabstractnormalvarsym(symtableentry);
|
||||||
{$if not defined(jvm) or defined(nounsupported)}
|
|
||||||
{ Nested variable }
|
{ Nested variable }
|
||||||
if assigned(left) then
|
if assigned(left) then
|
||||||
begin
|
generate_nested_access(vs)
|
||||||
secondpass(left);
|
|
||||||
if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
|
|
||||||
internalerror(200309286);
|
|
||||||
if vs.localloc.loc<>LOC_REFERENCE then
|
|
||||||
internalerror(200409241);
|
|
||||||
reference_reset_base(location.reference,left.location.register,vs.localloc.reference.offset,vs.localloc.reference.alignment);
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
{$endif}
|
|
||||||
location:=vs.localloc;
|
location:=vs.localloc;
|
||||||
|
|
||||||
{ handle call by reference variables when they are not
|
{ handle call by reference variables when they are not
|
||||||
|
@ -151,14 +151,6 @@ implementation
|
|||||||
hsym : tparavarsym;
|
hsym : tparavarsym;
|
||||||
href : treference;
|
href : treference;
|
||||||
begin
|
begin
|
||||||
{$ifdef jvm}
|
|
||||||
{$ifndef nounsupported}
|
|
||||||
location_reset(location,LOC_REGISTER,OS_ADDR);
|
|
||||||
location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,java_jlobject);
|
|
||||||
hlcg.a_load_const_reg(current_asmdata.CurrAsmList,java_jlobject,0,location.register);
|
|
||||||
exit;
|
|
||||||
{$endif nounsupported}
|
|
||||||
{$endif jvm}
|
|
||||||
if (current_procinfo.procdef.parast.symtablelevel=parentpd.parast.symtablelevel) then
|
if (current_procinfo.procdef.parast.symtablelevel=parentpd.parast.symtablelevel) then
|
||||||
begin
|
begin
|
||||||
location_reset(location,LOC_REGISTER,OS_ADDR);
|
location_reset(location,LOC_REGISTER,OS_ADDR);
|
||||||
|
197
compiler/ncgnstld.pas
Normal file
197
compiler/ncgnstld.pas
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
{
|
||||||
|
Copyright (c) 2011 by Jonas Maebe
|
||||||
|
|
||||||
|
Support for load nodes on targets that have to group all local variables
|
||||||
|
and parameters accessed by nested routines into structs (and then pass the
|
||||||
|
address of these structs to nested routines rather than the frame pointer,
|
||||||
|
and access the local variables as fields thereof)
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
****************************************************************************
|
||||||
|
}
|
||||||
|
unit ncgnstld;
|
||||||
|
|
||||||
|
{$i fpcdefs.inc}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
node,
|
||||||
|
symtype,
|
||||||
|
nld,
|
||||||
|
ncgld;
|
||||||
|
|
||||||
|
type
|
||||||
|
tcgnestloadnode = class(tcgloadnode)
|
||||||
|
protected
|
||||||
|
nestsym: tsym;
|
||||||
|
procedure generate_nested_access(vs: tsym);override;
|
||||||
|
public
|
||||||
|
function pass_typecheck: tnode; override;
|
||||||
|
function pass_1:tnode;override;
|
||||||
|
function dogetcopy: tnode; override;
|
||||||
|
function docompare(p: tnode): boolean; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
uses
|
||||||
|
cutils,verbose,globtype,globals,systems,constexp,
|
||||||
|
symnot,
|
||||||
|
defutil,defcmp,
|
||||||
|
htypechk,pass_1,procinfo,paramgr,
|
||||||
|
cpuinfo,
|
||||||
|
symconst,symbase,symsym,symdef,symtable,symcreat,
|
||||||
|
ncon,ninl,ncnv,nmem,ncal,nutils,nbas,
|
||||||
|
pass_2,cgbase
|
||||||
|
;
|
||||||
|
|
||||||
|
{*****************************************************************************
|
||||||
|
TCGNESTLOADNODE
|
||||||
|
*****************************************************************************}
|
||||||
|
|
||||||
|
procedure tcgnestloadnode.generate_nested_access(vs: tsym);
|
||||||
|
begin
|
||||||
|
{ left has been transformed into a string of accesses that result in
|
||||||
|
the location of the original variable's copy in the appropriate
|
||||||
|
parentfpstruct (via tcgnestloadparentfpnode.pass_1). In case it is a
|
||||||
|
var/out/constref parameter, that "copy" will have been a copy of the
|
||||||
|
address so the normal handling of such parameters in ncgld is ok) }
|
||||||
|
secondpass(left);
|
||||||
|
location:=left.location;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function tcgnestloadnode.pass_typecheck: tnode;
|
||||||
|
var
|
||||||
|
nestedvars: tsym;
|
||||||
|
begin
|
||||||
|
result:=inherited pass_typecheck;
|
||||||
|
if assigned(result) then
|
||||||
|
exit;
|
||||||
|
case symtableentry.typ of
|
||||||
|
paravarsym,
|
||||||
|
localvarsym :
|
||||||
|
begin
|
||||||
|
{ Nested variable? Then we have to move it to a structure that
|
||||||
|
can be passed by reference to nested routines }
|
||||||
|
if assigned(current_procinfo) and
|
||||||
|
(symtable.symtabletype in [localsymtable,parasymtable]) and
|
||||||
|
((symtable.symtablelevel<>current_procinfo.procdef.parast.symtablelevel) or
|
||||||
|
{ also redirect loads of locals/paras that have been moved to
|
||||||
|
the parentfpstruct inside the routine in which they were
|
||||||
|
originally declared, except in the initialisation code for
|
||||||
|
the parentfpstruct (nf_internal flag) }
|
||||||
|
(tabstractnormalvarsym(symtableentry).inparentfpstruct and
|
||||||
|
not(nf_internal in flags))) then
|
||||||
|
begin
|
||||||
|
{ get struct holding all locals accessed by nested routines }
|
||||||
|
nestedvars:=tprocdef(symtable.defowner).parentfpstruct;
|
||||||
|
{ don't add the parentfpstruct to itself! }
|
||||||
|
if nestedvars=symtableentry then
|
||||||
|
exit;
|
||||||
|
if not assigned(nestedvars) then
|
||||||
|
begin
|
||||||
|
{ create this struct }
|
||||||
|
build_parentfpstruct(tprocdef(symtable.defowner));
|
||||||
|
nestedvars:=tprocdef(symtable.defowner).parentfpstruct;
|
||||||
|
end;
|
||||||
|
{ store result for use in pass_1 }
|
||||||
|
nestsym:=maybe_add_sym_to_parentfpstruct(tprocdef(symtableentry.owner.defowner),symtableentry,resultdef,is_addr_param_load);
|
||||||
|
{ left normally holds the parentfp node. If it's not assigned,
|
||||||
|
this is an access to a local variable/para from the routine
|
||||||
|
in which it was actually declared -> redirect to its
|
||||||
|
equivalent in the parentfp struct }
|
||||||
|
if not assigned(left) then
|
||||||
|
begin
|
||||||
|
left:=caddrnode.create_internal(cloadnode.create(tprocdef(symtableentry.owner.defowner).parentfpstruct,tprocdef(symtableentry.owner.defowner).parentfpstruct.owner));
|
||||||
|
include(left.flags,nf_typedaddr);
|
||||||
|
end;
|
||||||
|
typecheckpass(left);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function tcgnestloadnode.pass_1:tnode;
|
||||||
|
var
|
||||||
|
thissym,
|
||||||
|
nestedvars: tsym;
|
||||||
|
nestedvarsdef: tdef;
|
||||||
|
begin
|
||||||
|
result:=inherited;
|
||||||
|
if assigned(result) then
|
||||||
|
exit;
|
||||||
|
case symtableentry.typ of
|
||||||
|
paravarsym,
|
||||||
|
localvarsym :
|
||||||
|
begin
|
||||||
|
{ Nested variable? Then we have to move it to a structure that
|
||||||
|
can be passed by reference to nested routines }
|
||||||
|
if assigned(current_procinfo) and
|
||||||
|
(symtable.symtabletype in [localsymtable,parasymtable]) and
|
||||||
|
((symtable.symtablelevel<>current_procinfo.procdef.parast.symtablelevel) or
|
||||||
|
(tabstractnormalvarsym(symtableentry).inparentfpstruct and
|
||||||
|
not(nf_internal in flags))) then
|
||||||
|
begin
|
||||||
|
{ get struct holding all locals accessed by nested routines }
|
||||||
|
nestedvars:=tprocdef(symtable.defowner).parentfpstruct;
|
||||||
|
if not assigned(nestedvars) then
|
||||||
|
begin
|
||||||
|
{ create this struct }
|
||||||
|
build_parentfpstruct(tprocdef(symtable.defowner));
|
||||||
|
nestedvars:=tprocdef(symtable.defowner).parentfpstruct;
|
||||||
|
end;
|
||||||
|
nestedvarsdef:=tlocalvarsym(nestedvars).vardef;
|
||||||
|
if nestedvars<>symtableentry then
|
||||||
|
thissym:=nestsym
|
||||||
|
else
|
||||||
|
thissym:=find_sym_in_parentfpstruct(tprocdef(symtableentry.owner.defowner),symtableentry);
|
||||||
|
if not assigned(thissym) then
|
||||||
|
internalerror(2011060406);
|
||||||
|
{ firstpass the parentfpnode. This will transform it into
|
||||||
|
a load of the appropriate parentfpstruct }
|
||||||
|
if not assigned(left) then
|
||||||
|
internalerror(2011060104);
|
||||||
|
firstpass(left);
|
||||||
|
{ subscript it to get the variable }
|
||||||
|
left:=csubscriptnode.create(thissym,cderefnode.create(left));
|
||||||
|
firstpass(left);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function tcgnestloadnode.dogetcopy: tnode;
|
||||||
|
begin
|
||||||
|
result:=inherited dogetcopy;
|
||||||
|
tcgnestloadnode(result).nestsym:=nestsym;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function tcgnestloadnode.docompare(p: tnode): boolean;
|
||||||
|
begin
|
||||||
|
result:=
|
||||||
|
inherited docompare(p) and
|
||||||
|
(tcgnestloadnode(p).nestsym=nestsym);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
begin
|
||||||
|
cloadnode:=tcgnestloadnode;
|
||||||
|
end.
|
130
compiler/ncgnstmm.pas
Normal file
130
compiler/ncgnstmm.pas
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
{
|
||||||
|
Copyright (c) 1998-2002 by Florian Klaempfl
|
||||||
|
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
****************************************************************************
|
||||||
|
}
|
||||||
|
unit ncgnstmm;
|
||||||
|
|
||||||
|
{$i fpcdefs.inc}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
globtype,cgbase,cpuinfo,cpubase,
|
||||||
|
node,ncgmem;
|
||||||
|
|
||||||
|
type
|
||||||
|
tcgnestloadparentfpnode = class(tcgloadparentfpnode)
|
||||||
|
function pass_typecheck: tnode; override;
|
||||||
|
function pass_1: tnode; override;
|
||||||
|
procedure pass_generate_code;override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
uses
|
||||||
|
systems,
|
||||||
|
cutils,cclasses,verbose,globals,constexp,
|
||||||
|
symconst,symdef,symsym,symtable,symcreat,defutil,paramgr,
|
||||||
|
aasmbase,aasmtai,aasmdata,
|
||||||
|
procinfo,pass_2,parabase,
|
||||||
|
pass_1,ncnv,nmem,nld,ncon,nadd,nutils,
|
||||||
|
cgutils,cgobj,hlcgobj,
|
||||||
|
tgobj,ncgutil,objcgutl
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
{*****************************************************************************
|
||||||
|
TCGLOADPARENTFPNODE
|
||||||
|
*****************************************************************************}
|
||||||
|
|
||||||
|
function tcgnestloadparentfpnode.pass_typecheck: tnode;
|
||||||
|
var
|
||||||
|
hsym : tparavarsym;
|
||||||
|
currpi,
|
||||||
|
nextpi : tprocinfo;
|
||||||
|
begin
|
||||||
|
result:=inherited;
|
||||||
|
if assigned(result) then
|
||||||
|
exit;
|
||||||
|
currpi:=current_procinfo.parent;
|
||||||
|
while (currpi.procdef.parast.symtablelevel>=parentpd.parast.symtablelevel) do
|
||||||
|
begin
|
||||||
|
if not assigned(currpi.procdef.parentfpstruct) then
|
||||||
|
build_parentfpstruct(currpi.procdef);
|
||||||
|
currpi:=currpi.parent;
|
||||||
|
end;
|
||||||
|
{ mark all parent parentfp parameters for inclusion in the struct that
|
||||||
|
holds all locals accessed from nested routines }
|
||||||
|
currpi:=current_procinfo.parent;
|
||||||
|
nextpi:=currpi.parent;
|
||||||
|
while (currpi.procdef.parast.symtablelevel>parentpd.parast.symtablelevel) do
|
||||||
|
begin
|
||||||
|
hsym:=tparavarsym(currpi.procdef.parast.Find('parentfp'));
|
||||||
|
maybe_add_sym_to_parentfpstruct(currpi.procdef,hsym,nextpi.procdef.parentfpstructptrtype,false);
|
||||||
|
currpi:=nextpi;
|
||||||
|
nextpi:=nextpi.parent;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function tcgnestloadparentfpnode.pass_1: tnode;
|
||||||
|
var
|
||||||
|
fsym : tfieldvarsym;
|
||||||
|
hsym : tparavarsym;
|
||||||
|
currpi,
|
||||||
|
nextpi : tprocinfo;
|
||||||
|
begin
|
||||||
|
result:=nil;
|
||||||
|
if not assigned(current_procinfo.procdef.parentfpstruct) then
|
||||||
|
begin
|
||||||
|
hsym:=tparavarsym(current_procinfo.procdef.parast.Find('parentfp'));
|
||||||
|
result:=cloadnode.create(hsym,hsym.owner);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
result:=caddrnode.create_internal(cloadnode.create(current_procinfo.procdef.parentfpstruct,current_procinfo.procdef.parentfpstruct.owner));
|
||||||
|
include(result.flags,nf_typedaddr);
|
||||||
|
end;
|
||||||
|
{ mark all parent parentfp parameters for inclusion in the struct that
|
||||||
|
holds all locals accessed from nested routines }
|
||||||
|
currpi:=current_procinfo.parent;
|
||||||
|
nextpi:=currpi.parent;
|
||||||
|
while (currpi.procdef.parast.symtablelevel>parentpd.parast.symtablelevel) do
|
||||||
|
begin
|
||||||
|
hsym:=tparavarsym(currpi.procdef.parast.Find('parentfp'));
|
||||||
|
fsym:=tfieldvarsym(find_sym_in_parentfpstruct(currpi.procdef,hsym));
|
||||||
|
if not assigned(fsym) then
|
||||||
|
internalerror(2011060405);
|
||||||
|
result:=csubscriptnode.create(fsym,cderefnode.create(result));
|
||||||
|
currpi:=nextpi;
|
||||||
|
nextpi:=nextpi.parent;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure tcgnestloadparentfpnode.pass_generate_code;
|
||||||
|
begin
|
||||||
|
{ should be handled in pass 1 }
|
||||||
|
internalerror(2011060202);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
begin
|
||||||
|
cloadparentfpnode:=tcgnestloadparentfpnode;
|
||||||
|
end.
|
@ -87,7 +87,7 @@ implementation
|
|||||||
systems,fpccrc,
|
systems,fpccrc,
|
||||||
cpuinfo,
|
cpuinfo,
|
||||||
{ symtable }
|
{ symtable }
|
||||||
symbase,symtable,defutil,defcmp,paramgr,cpupara,
|
symbase,symtable,symcreat,defutil,defcmp,paramgr,cpupara,
|
||||||
{ pass 1 }
|
{ pass 1 }
|
||||||
fmodule,node,htypechk,
|
fmodule,node,htypechk,
|
||||||
nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,
|
nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,
|
||||||
@ -229,12 +229,21 @@ implementation
|
|||||||
{$endif i386}
|
{$endif i386}
|
||||||
else
|
else
|
||||||
paranr:=paranr_parentfp_delphi_cc;
|
paranr:=paranr_parentfp_delphi_cc;
|
||||||
{ Generate result variable accessing function result, it
|
{ Generate frame pointer. It can't be put in a register since it
|
||||||
can't be put in a register since it must be accessable
|
must be accessable from nested routines }
|
||||||
from the framepointer }
|
if not(target_info.system in systems_fpnestedstruct) then
|
||||||
vs:=tparavarsym.create('$parentfp',paranr,vs_value
|
begin
|
||||||
,voidpointertype,[vo_is_parentfp,vo_is_hidden_para]);
|
vs:=tparavarsym.create('$parentfp',paranr,vs_value
|
||||||
vs.varregable:=vr_none;
|
,voidpointertype,[vo_is_parentfp,vo_is_hidden_para]);
|
||||||
|
vs.varregable:=vr_none;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if not assigned(tprocdef(pd.owner.defowner).parentfpstruct) then
|
||||||
|
build_parentfpstruct(tprocdef(pd.owner.defowner));
|
||||||
|
vs:=tparavarsym.create('$parentfp',paranr,vs_value
|
||||||
|
,tprocdef(pd.owner.defowner).parentfpstructptrtype,[vo_is_parentfp,vo_is_hidden_para]);
|
||||||
|
end;
|
||||||
pd.parast.insert(vs);
|
pd.parast.insert(vs);
|
||||||
|
|
||||||
current_tokenpos:=storepos;
|
current_tokenpos:=storepos;
|
||||||
|
@ -245,7 +245,9 @@ implementation
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
{ parse routine body }
|
||||||
block:=statement_block(_BEGIN);
|
block:=statement_block(_BEGIN);
|
||||||
|
{ initialized variables }
|
||||||
if current_procinfo.procdef.localst.symtabletype=localsymtable then
|
if current_procinfo.procdef.localst.symtabletype=localsymtable then
|
||||||
begin
|
begin
|
||||||
{ initialization of local variables with their initial
|
{ initialization of local variables with their initial
|
||||||
@ -255,6 +257,17 @@ implementation
|
|||||||
current_procinfo.procdef.localst.SymList.ForEachCall(@initializevars,block);
|
current_procinfo.procdef.localst.SymList.ForEachCall(@initializevars,block);
|
||||||
current_filepos:=oldfilepos;
|
current_filepos:=oldfilepos;
|
||||||
end;
|
end;
|
||||||
|
if assigned(current_procinfo.procdef.parentfpstruct) then
|
||||||
|
begin
|
||||||
|
{ we only do this after the code has been parsed because
|
||||||
|
otherwise for-loop counters moved to the struct cause
|
||||||
|
errors; we still do it nevertheless to prevent false
|
||||||
|
"unused" symbols warnings and to assist debug info
|
||||||
|
generation }
|
||||||
|
redirect_parentfpstruct_local_syms(current_procinfo.procdef);
|
||||||
|
{ finish the parentfpstruct (add padding, ...) }
|
||||||
|
finish_parentfpstruct(current_procinfo.procdef);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
block:=cnodeutils.wrap_proc_body(current_procinfo.procdef,block);
|
block:=cnodeutils.wrap_proc_body(current_procinfo.procdef,block);
|
||||||
end;
|
end;
|
||||||
@ -1486,6 +1499,14 @@ implementation
|
|||||||
|
|
||||||
{ Finish type checking pass }
|
{ Finish type checking pass }
|
||||||
do_typecheckpass(code);
|
do_typecheckpass(code);
|
||||||
|
|
||||||
|
if assigned(procdef.parentfpinitblock) then
|
||||||
|
begin
|
||||||
|
tblocknode(code).left:=cstatementnode.create(procdef.parentfpinitblock,tblocknode(code).left);
|
||||||
|
do_typecheckpass(tblocknode(code).left);
|
||||||
|
procdef.parentfpinitblock:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Check for unused labels, forwards, symbols for procedures. Static
|
{ Check for unused labels, forwards, symbols for procedures. Static
|
||||||
|
@ -28,7 +28,7 @@ interface
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
finput,tokens,scanner,
|
finput,tokens,scanner,
|
||||||
symconst,symdef,symbase;
|
symconst,symbase,symtype,symdef;
|
||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
@ -70,14 +70,40 @@ interface
|
|||||||
|
|
||||||
procedure finish_copied_procdef(var pd: tprocdef; const realname: string; newparentst: tsymtable; newstruct: tabstractrecorddef);
|
procedure finish_copied_procdef(var pd: tprocdef; const realname: string; newparentst: tsymtable; newstruct: tabstractrecorddef);
|
||||||
|
|
||||||
|
{ create "parent frame pointer" record skeleton for procdef, in which local
|
||||||
|
variables and parameters from pd accessed from nested routines can be
|
||||||
|
stored }
|
||||||
|
procedure build_parentfpstruct(pd: tprocdef);
|
||||||
|
{ checks whether sym (a local or para of pd) already has a counterpart in
|
||||||
|
pd's parentfpstruct, and if not adds a new field to the struct with type
|
||||||
|
"vardef" (can be different from sym's type in case it's a call-by-reference
|
||||||
|
parameter, which is indicated by addrparam). If it already has a field in
|
||||||
|
the parentfpstruct, this field is returned. }
|
||||||
|
function maybe_add_sym_to_parentfpstruct(pd: tprocdef; sym: tsym; vardef: tdef; addrparam: boolean): tsym;
|
||||||
|
{ given a localvarsym or paravarsym of pd, returns the field of the
|
||||||
|
parentfpstruct corresponding to this sym }
|
||||||
|
function find_sym_in_parentfpstruct(pd: tprocdef; sym: tsym): tsym;
|
||||||
|
{ replaces all local and paravarsyms that have been mirrored in the
|
||||||
|
parentfpstruct with aliasvarsyms that redirect to these fields (used to
|
||||||
|
make sure that references to these syms in the owning procdef itself also
|
||||||
|
use the ones in the parentfpstructs) }
|
||||||
|
procedure redirect_parentfpstruct_local_syms(pd: tprocdef);
|
||||||
|
{ finalises the parentfpstruct (alignment padding, ...) }
|
||||||
|
procedure finish_parentfpstruct(pd: tprocdef);
|
||||||
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
cutils,globtype,globals,verbose,systems,comphook,
|
cutils,globtype,globals,verbose,systems,comphook,fmodule,
|
||||||
symtype,symsym,symtable,defutil,
|
symsym,symtable,defutil,
|
||||||
pbase,pdecobj,pdecsub,psub,
|
pbase,pdecobj,pdecsub,psub,
|
||||||
defcmp;
|
node,nbas,nld,nmem,
|
||||||
|
defcmp,
|
||||||
|
paramgr
|
||||||
|
{$ifdef jvm}
|
||||||
|
,pjvm
|
||||||
|
{$endif};
|
||||||
|
|
||||||
procedure replace_scanner(const tempname: string; out sstate: tscannerstate);
|
procedure replace_scanner(const tempname: string; out sstate: tscannerstate);
|
||||||
var
|
var
|
||||||
@ -366,7 +392,12 @@ implementation
|
|||||||
for i:=0 to st.deflist.count-1 do
|
for i:=0 to st.deflist.count-1 do
|
||||||
begin
|
begin
|
||||||
def:=tdef(st.deflist[i]);
|
def:=tdef(st.deflist[i]);
|
||||||
if (is_javaclass(def) and
|
if (def.typ=procdef) and
|
||||||
|
assigned(tprocdef(def).localst) and
|
||||||
|
{ not true for the "main" procedure, whose localsymtable is the staticsymtable }
|
||||||
|
(tprocdef(def).localst.symtabletype=localsymtable) then
|
||||||
|
add_synthetic_method_implementations(tprocdef(def).localst)
|
||||||
|
else if (is_javaclass(def) and
|
||||||
not(oo_is_external in tobjectdef(def).objectoptions)) or
|
not(oo_is_external in tobjectdef(def).objectoptions)) or
|
||||||
(def.typ=recorddef) then
|
(def.typ=recorddef) then
|
||||||
begin
|
begin
|
||||||
@ -386,7 +417,6 @@ implementation
|
|||||||
sym: tsym;
|
sym: tsym;
|
||||||
parasym: tparavarsym;
|
parasym: tparavarsym;
|
||||||
ps: tprocsym;
|
ps: tprocsym;
|
||||||
hdef: tdef;
|
|
||||||
stname: string;
|
stname: string;
|
||||||
i: longint;
|
i: longint;
|
||||||
begin
|
begin
|
||||||
@ -433,5 +463,158 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure build_parentfpstruct(pd: tprocdef);
|
||||||
|
var
|
||||||
|
nestedvars: tsym;
|
||||||
|
nestedvarsst: tsymtable;
|
||||||
|
pnestedvarsdef,
|
||||||
|
nestedvarsdef: tdef;
|
||||||
|
old_symtablestack: tsymtablestack;
|
||||||
|
begin
|
||||||
|
{ make sure the defs are not registered in the current symtablestack,
|
||||||
|
because they may be for a parent procdef (changeowner does remove a def
|
||||||
|
from the symtable in which it was originally created, so that by itself
|
||||||
|
is not enough) }
|
||||||
|
old_symtablestack:=symtablestack;
|
||||||
|
symtablestack:=old_symtablestack.getcopyuntil(current_module.localsymtable);
|
||||||
|
{ create struct to hold local variables and parameters that are
|
||||||
|
accessed from within nested routines }
|
||||||
|
nestedvarsst:=trecordsymtable.create(current_module.realmodulename^+'$$_fpc_nestedvars$'+tostr(pd.procsym.symid),current_settings.alignment.localalignmax);
|
||||||
|
nestedvarsdef:=trecorddef.create(nestedvarsst.name^,nestedvarsst);
|
||||||
|
{$ifdef jvm}
|
||||||
|
jvm_guarantee_record_typesym(nestedvarsdef,nestedvarsdef.owner);
|
||||||
|
{ don't add clone/FpcDeepCopy, because the field names are not all
|
||||||
|
representable in source form and we don't need them anyway }
|
||||||
|
symtablestack.push(trecorddef(nestedvarsdef).symtable);
|
||||||
|
maybe_add_public_default_java_constructor(trecorddef(nestedvarsdef));
|
||||||
|
symtablestack.pop(trecorddef(nestedvarsdef).symtable);
|
||||||
|
{$endif}
|
||||||
|
symtablestack.free;
|
||||||
|
symtablestack:=old_symtablestack.getcopyuntil(pd.localst);
|
||||||
|
pnestedvarsdef:=tpointerdef.create(nestedvarsdef);
|
||||||
|
nestedvars:=tlocalvarsym.create('$nestedvars',vs_var,nestedvarsdef,[]);
|
||||||
|
pd.localst.insert(nestedvars);
|
||||||
|
pd.parentfpstruct:=nestedvars;
|
||||||
|
pd.parentfpstructptrtype:=pnestedvarsdef;
|
||||||
|
|
||||||
|
pd.parentfpinitblock:=cblocknode.create(nil);
|
||||||
|
symtablestack.free;
|
||||||
|
symtablestack:=old_symtablestack;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function maybe_add_sym_to_parentfpstruct(pd: tprocdef; sym: tsym; vardef: tdef; addrparam: boolean): tsym;
|
||||||
|
var
|
||||||
|
fieldvardef,
|
||||||
|
nestedvarsdef: tdef;
|
||||||
|
nestedvarsst: tsymtable;
|
||||||
|
initcode: tnode;
|
||||||
|
old_filepos: tfileposinfo;
|
||||||
|
begin
|
||||||
|
nestedvarsdef:=tlocalvarsym(pd.parentfpstruct).vardef;
|
||||||
|
result:=search_struct_member(trecorddef(nestedvarsdef),sym.name);
|
||||||
|
if not assigned(result) then
|
||||||
|
begin
|
||||||
|
{ mark that this symbol is mirrored in the parentfpstruct }
|
||||||
|
tabstractnormalvarsym(sym).inparentfpstruct:=true;
|
||||||
|
{ add field to the struct holding all locals accessed
|
||||||
|
by nested routines }
|
||||||
|
nestedvarsst:=trecorddef(nestedvarsdef).symtable;
|
||||||
|
{ indicate whether or not this is a var/out/constref/... parameter }
|
||||||
|
if addrparam then
|
||||||
|
fieldvardef:=tpointerdef.create(vardef)
|
||||||
|
else
|
||||||
|
fieldvardef:=vardef;
|
||||||
|
result:=tfieldvarsym.create(sym.realname,vs_value,fieldvardef,[]);
|
||||||
|
if nestedvarsst.symlist.count=0 then
|
||||||
|
include(tfieldvarsym(result).varoptions,vo_is_first_field);
|
||||||
|
nestedvarsst.insert(result);
|
||||||
|
trecordsymtable(nestedvarsst).addfield(tfieldvarsym(result),vis_public);
|
||||||
|
|
||||||
|
{ add initialization with original value if it's a parameter }
|
||||||
|
if (sym.typ=paravarsym) then
|
||||||
|
begin
|
||||||
|
old_filepos:=current_filepos;
|
||||||
|
fillchar(current_filepos,sizeof(current_filepos),0);
|
||||||
|
initcode:=cloadnode.create(sym,sym.owner);
|
||||||
|
{ indicate that this load should not be transformed into a load
|
||||||
|
from the parentfpstruct, but instead should load the original
|
||||||
|
value }
|
||||||
|
include(initcode.flags,nf_internal);
|
||||||
|
{ in case it's a var/out/constref parameter, store the address of the
|
||||||
|
parameter in the struct }
|
||||||
|
if addrparam then
|
||||||
|
begin
|
||||||
|
initcode:=caddrnode.create_internal(initcode);
|
||||||
|
include(initcode.flags,nf_typedaddr);
|
||||||
|
end;
|
||||||
|
initcode:=cassignmentnode.create(
|
||||||
|
csubscriptnode.create(result,cloadnode.create(pd.parentfpstruct,pd.parentfpstruct.owner)),
|
||||||
|
initcode);
|
||||||
|
tblocknode(pd.parentfpinitblock).left:=cstatementnode.create
|
||||||
|
(initcode,tblocknode(pd.parentfpinitblock).left);
|
||||||
|
current_filepos:=old_filepos;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure redirect_parentfpstruct_local_syms(pd: tprocdef);
|
||||||
|
var
|
||||||
|
nestedvarsdef: trecorddef;
|
||||||
|
sl: tpropaccesslist;
|
||||||
|
fsym,
|
||||||
|
lsym,
|
||||||
|
aliassym: tsym;
|
||||||
|
i: longint;
|
||||||
|
begin
|
||||||
|
nestedvarsdef:=trecorddef(tlocalvarsym(pd.parentfpstruct).vardef);
|
||||||
|
for i:=0 to nestedvarsdef.symtable.symlist.count-1 do
|
||||||
|
begin
|
||||||
|
fsym:=tsym(nestedvarsdef.symtable.symlist[i]);
|
||||||
|
if fsym.typ<>fieldvarsym then
|
||||||
|
continue;
|
||||||
|
lsym:=tsym(pd.localst.find(fsym.name));
|
||||||
|
if not assigned(lsym) then
|
||||||
|
lsym:=tsym(pd.parast.find(fsym.name));
|
||||||
|
if not assigned(lsym) then
|
||||||
|
internalerror(2011060408);
|
||||||
|
{ add an absolute variable that redirects to the field }
|
||||||
|
sl:=tpropaccesslist.create;
|
||||||
|
sl.addsym(sl_load,pd.parentfpstruct);
|
||||||
|
sl.addsym(sl_subscript,tfieldvarsym(fsym));
|
||||||
|
aliassym:=tabsolutevarsym.create_ref(lsym.name,tfieldvarsym(fsym).vardef,sl);
|
||||||
|
{ hide the original variable (can't delete, because there
|
||||||
|
may be other loadnodes that reference it)
|
||||||
|
-- only for locals; hiding parameters changes the
|
||||||
|
function signature }
|
||||||
|
if lsym.typ<>paravarsym then
|
||||||
|
hidesym(lsym);
|
||||||
|
{ insert the absolute variable in the localst of the
|
||||||
|
routine; ignore duplicates, because this will also check the
|
||||||
|
parasymtable and we want to override parameters with our local
|
||||||
|
versions }
|
||||||
|
pd.localst.insert(aliassym,false);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function find_sym_in_parentfpstruct(pd: tprocdef; sym: tsym): tsym;
|
||||||
|
var
|
||||||
|
nestedvarsdef: tdef;
|
||||||
|
begin
|
||||||
|
nestedvarsdef:=tlocalvarsym(pd.parentfpstruct).vardef;
|
||||||
|
result:=search_struct_member(trecorddef(nestedvarsdef),sym.name);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure finish_parentfpstruct(pd: tprocdef);
|
||||||
|
begin
|
||||||
|
trecordsymtable(trecorddef(tlocalvarsym(pd.parentfpstruct).vardef).symtable).addalignmentpadding;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -559,6 +559,19 @@ interface
|
|||||||
easily write out all methods grouped per class }
|
easily write out all methods grouped per class }
|
||||||
exprasmlist : TAsmList;
|
exprasmlist : TAsmList;
|
||||||
{$endif jvm}
|
{$endif jvm}
|
||||||
|
{ temporary reference to structure containing copies of all local
|
||||||
|
variables and parameters accessed by nested routines; reference to
|
||||||
|
this structure is passed as "parent frame pointer" on targets that
|
||||||
|
lack this concept (at least JVM and LLVM); no need to save to/
|
||||||
|
restore from ppu, since nested routines are always in the same
|
||||||
|
unit (no need to save to ppu) }
|
||||||
|
parentfpstruct: tsym;
|
||||||
|
{ pointer to parentfpstruct's type (not yet valid during parsing, so
|
||||||
|
cannot be used for $parentfp parameter) (no need to save to ppu) }
|
||||||
|
parentfpstructptrtype: tdef;
|
||||||
|
{ code to copy the parameters accessed from nested routines into the
|
||||||
|
parentfpstruct (no need to save to ppu) }
|
||||||
|
parentfpinitblock: tnode;
|
||||||
{$ifdef oldregvars}
|
{$ifdef oldregvars}
|
||||||
regvarinfo: pregvarinfo;
|
regvarinfo: pregvarinfo;
|
||||||
{$endif oldregvars}
|
{$endif oldregvars}
|
||||||
|
@ -173,6 +173,7 @@ interface
|
|||||||
defaultconstsymderef : tderef;
|
defaultconstsymderef : tderef;
|
||||||
localloc : TLocation; { register/reference for local var }
|
localloc : TLocation; { register/reference for local var }
|
||||||
initialloc : TLocation; { initial location so it can still be initialized later after the location was changed by SSA }
|
initialloc : TLocation; { initial location so it can still be initialized later after the location was changed by SSA }
|
||||||
|
inparentfpstruct : boolean; { migrated to a parentfpstruct because of nested access (not written to ppu, because not important and would change interface crc) }
|
||||||
constructor create(st:tsymtyp;const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
|
constructor create(st:tsymtyp;const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
|
||||||
constructor ppuload(st:tsymtyp;ppufile:tcompilerppufile);
|
constructor ppuload(st:tsymtyp;ppufile:tcompilerppufile);
|
||||||
procedure ppuwrite(ppufile:tcompilerppufile);override;
|
procedure ppuwrite(ppufile:tcompilerppufile);override;
|
||||||
|
@ -323,6 +323,13 @@ interface
|
|||||||
system_jvm_java32
|
system_jvm_java32
|
||||||
];
|
];
|
||||||
|
|
||||||
|
{ all systems that don't use a built-in framepointer for accessing nested
|
||||||
|
variables, but emulate it by wrapping nested variables in records
|
||||||
|
whose address is passed around }
|
||||||
|
systems_fpnestedstruct = [
|
||||||
|
system_jvm_java32
|
||||||
|
];
|
||||||
|
|
||||||
cpu2str : array[TSystemCpu] of string[10] =
|
cpu2str : array[TSystemCpu] of string[10] =
|
||||||
('','i386','m68k','alpha','powerpc','sparc','vm','ia64','x86_64',
|
('','i386','m68k','alpha','powerpc','sparc','vm','ia64','x86_64',
|
||||||
'mips','arm', 'powerpc64', 'avr', 'mipsel','jvm');
|
'mips','arm', 'powerpc64', 'avr', 'mipsel','jvm');
|
||||||
|
Loading…
Reference in New Issue
Block a user