* initialise local dynamic array variables to empty arrays rather than

to "nil", so that returning them to Java code does not return a nil
    pointer

git-svn-id: branches/jvmbackend@18417 -
This commit is contained in:
Jonas Maebe 2011-08-20 07:57:55 +00:00
parent f58de91f0c
commit 761ff19c7f
3 changed files with 71 additions and 10 deletions

View File

@ -35,6 +35,8 @@ interface
function typecheck_length(var handled: boolean): tnode;
function typecheck_high(var handled: boolean): tnode;
function typecheck_new(var handled: boolean): tnode;
function first_setlength_array: tnode;
public
{ typecheck override to intercept handling }
function pass_typecheck: tnode; override;
@ -65,6 +67,7 @@ interface
procedure second_round_real; override;
*)
procedure second_new; override;
procedure second_setlength; override;
protected
procedure load_fpu_location;
end;
@ -74,9 +77,9 @@ implementation
uses
cutils,globals,verbose,globtype,constexp,
aasmbase,aasmtai,aasmdata,aasmcpu,
symtype,symconst,symdef,symtable,jvmdef,
symtype,symconst,symdef,symsym,symtable,jvmdef,
defutil,
nbas,ncon,ncnv,ncal,nld,
nbas,ncon,ncnv,ncal,nld,nflw,nutils,
cgbase,pass_1,pass_2,
cpuinfo,ncgutil,
cgutils,hlcgobj,hlcgcpu;
@ -216,7 +219,7 @@ implementation
end;
function tjvminlinenode.first_setlength: tnode;
function tjvminlinenode.first_setlength_array: tnode;
var
assignmenttarget,
ppn,
@ -232,8 +235,6 @@ implementation
newstatement: tstatementnode;
primitive: boolean;
begin
{ reverse the parameter order so we can process them more easily }
left:=reverseparameters(tcallparanode(left));
{ first parameter is the array, the rest are the dimensions }
newparas:=tcallparanode(left).right;
tcallparanode(left).right:=nil;
@ -333,6 +334,29 @@ implementation
end;
function tjvminlinenode.first_setlength: tnode;
begin
{ reverse the parameter order so we can process them more easily }
left:=reverseparameters(tcallparanode(left));
{ treat setlength(x,0) specially: used to init uninitialised locations }
if not assigned(tcallparanode(tcallparanode(left).right).right) and
is_constintnode(tcallparanode(tcallparanode(left).right).left) and
(tordconstnode(tcallparanode(tcallparanode(left).right).left).value=0) then
begin
result:=nil;
expectloc:=LOC_VOID;
exit;
end;
case left.resultdef.typ of
arraydef:
result:=first_setlength_array;
else
internalerror(2011031204);
end;
end;
procedure tjvminlinenode.second_length;
begin
if is_dynamic_array(left.resultdef) or
@ -469,6 +493,30 @@ implementation
end;
procedure tjvminlinenode.second_setlength;
var
target: tnode;
lenpara: tnode;
begin
target:=tcallparanode(left).left;
lenpara:=tcallparanode(tcallparanode(left).right).left;
if assigned(tcallparanode(tcallparanode(left).right).right) or
not is_constintnode(lenpara) or
(tordconstnode(lenpara).value<>0) then
internalerror(2011031801);
secondpass(target);
if is_dynamic_array(target.resultdef) then
begin
thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,s32inttype,0,R_INTREGISTER);
thlcgjvm(hlcg).g_newarray(current_asmdata.CurrAsmList,target.resultdef,1);
end
else
internalerror(2011031401);
thlcgjvm(hlcg).a_load_stack_loc(current_asmdata.CurrAsmList,target.resultdef,target.location);
end;
begin
cinlinenode:=tjvminlinenode;
end.

View File

@ -42,7 +42,7 @@ implementation
uses
verbose,constexp,
symconst,symtype,symdef,symsym,symbase,symtable,defutil,
nbas,ncnv,ncon,nld,
nbas,ncnv,ncon,ninl,ncal,
pass_1;
class function tjvmnodeutils.initialize_data_node(p:tnode):tnode;
@ -54,10 +54,20 @@ implementation
not is_longstring(p.resultdef)) or
is_dynamic_array(p.resultdef) then
begin
result:=cassignmentnode.create(
ctypeconvnode.create_internal(p,voidpointertype),
cnilnode.create
);
{ Always initialise with empty string/array rather than nil. Java
makes a distinction between an empty string/array and a null
string/array, but we don't. We therefore have to pick which one we
use to represent empty strings/arrays. I've chosen empty rather than
null structures, because otherwise it becomes impossible to return
an empty string to Java code (it would return null).
On the consumer side, we do interpret both null and empty as the same
thing, so Java code can pass in null strings/arrays and we'll
interpret them correctly.
}
result:=cinlinenode.create(in_setlength_x,false,
ccallparanode.create(genintconstnode(0),
ccallparanode.create(p,nil)));
end
else
{ records/arrays/... are automatically initialised }

View File

@ -58,6 +58,7 @@ interface
procedure second_sar; virtual;
procedure second_bsfbsr; virtual;
procedure second_new; virtual;
procedure second_setlength; virtual; abstract;
end;
implementation
@ -176,6 +177,8 @@ implementation
second_BsfBsr;
in_new_x:
second_new;
in_setlength_x:
second_setlength;
else internalerror(9);
end;
end;