* 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_length(var handled: boolean): tnode;
function typecheck_high(var handled: boolean): tnode; function typecheck_high(var handled: boolean): tnode;
function typecheck_new(var handled: boolean): tnode; function typecheck_new(var handled: boolean): tnode;
function first_setlength_array: tnode;
public public
{ typecheck override to intercept handling } { typecheck override to intercept handling }
function pass_typecheck: tnode; override; function pass_typecheck: tnode; override;
@ -65,6 +67,7 @@ interface
procedure second_round_real; override; procedure second_round_real; override;
*) *)
procedure second_new; override; procedure second_new; override;
procedure second_setlength; override;
protected protected
procedure load_fpu_location; procedure load_fpu_location;
end; end;
@ -74,9 +77,9 @@ implementation
uses uses
cutils,globals,verbose,globtype,constexp, cutils,globals,verbose,globtype,constexp,
aasmbase,aasmtai,aasmdata,aasmcpu, aasmbase,aasmtai,aasmdata,aasmcpu,
symtype,symconst,symdef,symtable,jvmdef, symtype,symconst,symdef,symsym,symtable,jvmdef,
defutil, defutil,
nbas,ncon,ncnv,ncal,nld, nbas,ncon,ncnv,ncal,nld,nflw,nutils,
cgbase,pass_1,pass_2, cgbase,pass_1,pass_2,
cpuinfo,ncgutil, cpuinfo,ncgutil,
cgutils,hlcgobj,hlcgcpu; cgutils,hlcgobj,hlcgcpu;
@ -216,7 +219,7 @@ implementation
end; end;
function tjvminlinenode.first_setlength: tnode; function tjvminlinenode.first_setlength_array: tnode;
var var
assignmenttarget, assignmenttarget,
ppn, ppn,
@ -232,8 +235,6 @@ implementation
newstatement: tstatementnode; newstatement: tstatementnode;
primitive: boolean; primitive: boolean;
begin 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 } { first parameter is the array, the rest are the dimensions }
newparas:=tcallparanode(left).right; newparas:=tcallparanode(left).right;
tcallparanode(left).right:=nil; tcallparanode(left).right:=nil;
@ -333,6 +334,29 @@ implementation
end; 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; procedure tjvminlinenode.second_length;
begin begin
if is_dynamic_array(left.resultdef) or if is_dynamic_array(left.resultdef) or
@ -469,6 +493,30 @@ implementation
end; 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 begin
cinlinenode:=tjvminlinenode; cinlinenode:=tjvminlinenode;
end. end.

View File

@ -42,7 +42,7 @@ implementation
uses uses
verbose,constexp, verbose,constexp,
symconst,symtype,symdef,symsym,symbase,symtable,defutil, symconst,symtype,symdef,symsym,symbase,symtable,defutil,
nbas,ncnv,ncon,nld, nbas,ncnv,ncon,ninl,ncal,
pass_1; pass_1;
class function tjvmnodeutils.initialize_data_node(p:tnode):tnode; class function tjvmnodeutils.initialize_data_node(p:tnode):tnode;
@ -54,10 +54,20 @@ implementation
not is_longstring(p.resultdef)) or not is_longstring(p.resultdef)) or
is_dynamic_array(p.resultdef) then is_dynamic_array(p.resultdef) then
begin begin
result:=cassignmentnode.create( { Always initialise with empty string/array rather than nil. Java
ctypeconvnode.create_internal(p,voidpointertype), makes a distinction between an empty string/array and a null
cnilnode.create 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 end
else else
{ records/arrays/... are automatically initialised } { records/arrays/... are automatically initialised }

View File

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