fpc/compiler/jvm/njvmcal.pas
Jonas Maebe be4a27657b + support for nested Java classes
o tobjectdef.jvm_full_typename() now gets an extra parameter to determine
     whether or not the package name should be prepended, so it can be easily
     used to generate the name of the .j file and of the class name inside it

git-svn-id: branches/jvmbackend@18384 -
2011-08-20 07:55:03 +00:00

138 lines
4.7 KiB
ObjectPascal

{
Copyright (c) 2011 by Jonas Maebe
JVM-specific code for call nodes
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 njvmcal;
{$i fpcdefs.inc}
interface
uses
symdef,
ncgcal;
type
{ tjvmcallnode }
tjvmcallnode = class(tcgcallnode)
protected
procedure extra_pre_call_code; override;
procedure set_result_location(realresdef: tstoreddef); override;
procedure do_release_unused_return_value;override;
procedure extra_post_call_code; override;
end;
implementation
uses
verbose,globtype,
symconst,symtype,defutil,ncal,
cgbase,cgutils,tgobj,procinfo,
cpubase,aasmdata,aasmcpu,
hlcgobj,hlcgcpu,
jvmdef;
{*****************************************************************************
TJVMCALLNODE
*****************************************************************************}
procedure tjvmcallnode.extra_pre_call_code;
begin
{ when calling a constructor, first create a new instance, except
when calling it from another constructor (because then this has
already been done before calling the current constructor) }
if procdefinition.typ<>procdef then
exit;
if tprocdef(procdefinition).proctypeoption<>potype_constructor then
exit;
if (methodpointer.resultdef.typ<>classrefdef) then
exit;
current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_new,current_asmdata.RefAsmSymbol(tobjectdef(tprocdef(procdefinition).owner.defowner).jvm_full_typename(true))));
{ the constructor doesn't return anything, so put a duplicate of the
self pointer on the evaluation stack for use as function result
after the constructor has run }
current_asmdata.CurrAsmList.concat(taicpu.op_none(a_dup));
thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,2);
end;
procedure tjvmcallnode.set_result_location(realresdef: tstoreddef);
begin
location_reset_ref(location,LOC_REFERENCE,def_cgsize(realresdef),1);
tg.gethltemp(current_asmdata.CurrAsmList,realresdef,realresdef.size,tt_normal,location.reference);
end;
procedure tjvmcallnode.do_release_unused_return_value;
begin
if (tprocdef(procdefinition).proctypeoption=potype_constructor) and
(current_procinfo.procdef.proctypeoption=potype_constructor) then
exit;
case resultdef.size of
0:
;
1..4:
begin
current_asmdata.CurrAsmList.concat(taicpu.op_none(a_pop));
thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,1);
end;
8:
begin
current_asmdata.CurrAsmList.concat(taicpu.op_none(a_pop2));
thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,2);
end
else
internalerror(2011010305);
end;
end;
procedure tjvmcallnode.extra_post_call_code;
var
totalremovesize: longint;
realresdef: tdef;
begin
if not assigned(typedef) then
realresdef:=tstoreddef(resultdef)
else
realresdef:=tstoreddef(typedef);
{ a constructor doesn't actually return a value in the jvm }
if (tprocdef(procdefinition).proctypeoption=potype_constructor) then
totalremovesize:=pushedparasize
else
{ even a byte takes up a full stackslot -> align size to multiple of 4 }
totalremovesize:=pushedparasize-(align(realresdef.size,4) shr 2);
{ remove parameters from internal evaluation stack counter (in case of
e.g. no parameters and a result, it can also increase) }
if totalremovesize>0 then
thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,totalremovesize)
else if totalremovesize<0 then
thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,-totalremovesize);
end;
begin
ccallnode:=tjvmcallnode;
end.