mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-23 18:49:49 +02:00
* 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:
parent
f58de91f0c
commit
761ff19c7f
compiler
@ -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.
|
||||
|
@ -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 }
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user