mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-16 04:49:19 +02:00
* since enums are represented by classes in the JVM, initialize global
variables, class/record fields and arrays with enumtype(0) on creation, so that using them without explicitly initializing them doesn't cause a null-pointer exception. If enumtype(0) is not a valid enum, they are not initialized (and since they wouldn't have a valid value on native targets either in that case, an exception on use is acceptable) git-svn-id: branches/jvmbackend@18755 -
This commit is contained in:
parent
48710a5a3f
commit
76de70e683
@ -155,7 +155,10 @@ uses
|
|||||||
|
|
||||||
procedure gen_initialize_fields_code(list:TAsmList);
|
procedure gen_initialize_fields_code(list:TAsmList);
|
||||||
protected
|
protected
|
||||||
|
function get_enum_init_val_ref(def: tdef; out ref: treference): boolean;
|
||||||
|
|
||||||
procedure allocate_implicit_structs_for_st_with_base_ref(list: TAsmList; st: tsymtable; const ref: treference; allocvartyp: tsymtyp);
|
procedure allocate_implicit_structs_for_st_with_base_ref(list: TAsmList; st: tsymtable; const ref: treference; allocvartyp: tsymtyp);
|
||||||
|
procedure allocate_enum_with_base_ref(list: TAsmList; vs: tabstractvarsym; const initref: treference; destbaseref: treference);
|
||||||
procedure allocate_implicit_struct_with_base_ref(list: TAsmList; vs: tabstractvarsym; ref: treference);
|
procedure allocate_implicit_struct_with_base_ref(list: TAsmList; vs: tabstractvarsym; ref: treference);
|
||||||
procedure gen_load_uninitialized_function_result(list: TAsmList; pd: tprocdef; resdef: tdef; const resloc: tcgpara); override;
|
procedure gen_load_uninitialized_function_result(list: TAsmList; pd: tprocdef; resdef: tdef; const resloc: tcgpara); override;
|
||||||
|
|
||||||
@ -605,7 +608,8 @@ implementation
|
|||||||
|
|
||||||
procedure thlcgjvm.g_newarray(list: TAsmList; arrdef: tdef; initdim: longint);
|
procedure thlcgjvm.g_newarray(list: TAsmList; arrdef: tdef; initdim: longint);
|
||||||
var
|
var
|
||||||
recref: treference;
|
recref,
|
||||||
|
enuminitref: treference;
|
||||||
elemdef: tdef;
|
elemdef: tdef;
|
||||||
i: longint;
|
i: longint;
|
||||||
mangledname: string;
|
mangledname: string;
|
||||||
@ -646,38 +650,47 @@ implementation
|
|||||||
for i:=1 to pred(initdim) do
|
for i:=1 to pred(initdim) do
|
||||||
elemdef:=tarraydef(elemdef).elementdef;
|
elemdef:=tarraydef(elemdef).elementdef;
|
||||||
if (elemdef.typ in [recorddef,setdef]) or
|
if (elemdef.typ in [recorddef,setdef]) or
|
||||||
|
((elemdef.typ=enumdef) and
|
||||||
|
get_enum_init_val_ref(elemdef,enuminitref)) or
|
||||||
is_shortstring(elemdef) or
|
is_shortstring(elemdef) or
|
||||||
((elemdef.typ=procvardef) and
|
((elemdef.typ=procvardef) and
|
||||||
not tprocvardef(elemdef).is_addressonly) then
|
not tprocvardef(elemdef).is_addressonly) then
|
||||||
begin
|
begin
|
||||||
{ duplicate array/string/set instance }
|
{ duplicate array instance }
|
||||||
list.concat(taicpu.op_none(a_dup));
|
list.concat(taicpu.op_none(a_dup));
|
||||||
incstack(list,1);
|
incstack(list,1);
|
||||||
a_load_const_stack(list,s32inttype,initdim-1,R_INTREGISTER);
|
a_load_const_stack(list,s32inttype,initdim-1,R_INTREGISTER);
|
||||||
if elemdef.typ in [recorddef,setdef,procvardef] then
|
case elemdef.typ of
|
||||||
begin
|
recorddef,setdef,procvardef:
|
||||||
tg.gethltemp(list,elemdef,elemdef.size,tt_persistent,recref);
|
begin
|
||||||
a_load_ref_stack(list,elemdef,recref,prepare_stack_for_ref(list,recref,false));
|
tg.gethltemp(list,elemdef,elemdef.size,tt_persistent,recref);
|
||||||
case elemdef.typ of
|
a_load_ref_stack(list,elemdef,recref,prepare_stack_for_ref(list,recref,false));
|
||||||
recorddef:
|
case elemdef.typ of
|
||||||
g_call_system_proc(list,'fpc_initialize_array_record');
|
recorddef:
|
||||||
setdef:
|
g_call_system_proc(list,'fpc_initialize_array_record');
|
||||||
begin
|
setdef:
|
||||||
if tsetdef(elemdef).elementdef.typ=enumdef then
|
begin
|
||||||
g_call_system_proc(list,'fpc_initialize_array_enumset')
|
if tsetdef(elemdef).elementdef.typ=enumdef then
|
||||||
else
|
g_call_system_proc(list,'fpc_initialize_array_enumset')
|
||||||
g_call_system_proc(list,'fpc_initialize_array_bitset')
|
else
|
||||||
end;
|
g_call_system_proc(list,'fpc_initialize_array_bitset')
|
||||||
procvardef:
|
end;
|
||||||
g_call_system_proc(list,'fpc_initialize_array_procvar');
|
procvardef:
|
||||||
|
g_call_system_proc(list,'fpc_initialize_array_procvar');
|
||||||
|
end;
|
||||||
|
tg.ungettemp(list,recref);
|
||||||
end;
|
end;
|
||||||
tg.ungettemp(list,recref);
|
enumdef:
|
||||||
end
|
begin
|
||||||
else
|
a_load_ref_stack(list,java_jlobject,enuminitref,prepare_stack_for_ref(list,enuminitref,false));
|
||||||
begin
|
g_call_system_proc(list,'fpc_initialize_array_object');
|
||||||
a_load_const_stack(list,u8inttype,tstringdef(elemdef).len,R_INTREGISTER);
|
end;
|
||||||
g_call_system_proc(list,'fpc_initialize_array_shortstring');
|
else
|
||||||
end;
|
begin
|
||||||
|
a_load_const_stack(list,u8inttype,tstringdef(elemdef).len,R_INTREGISTER);
|
||||||
|
g_call_system_proc(list,'fpc_initialize_array_shortstring');
|
||||||
|
end;
|
||||||
|
end;
|
||||||
decstack(list,3);
|
decstack(list,3);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1495,6 +1508,14 @@ implementation
|
|||||||
g_call_system_proc(list,'fpc_initialize_array_bitset');
|
g_call_system_proc(list,'fpc_initialize_array_bitset');
|
||||||
tg.ungettemp(list,eleref);
|
tg.ungettemp(list,eleref);
|
||||||
end
|
end
|
||||||
|
else if (t.typ=enumdef) then
|
||||||
|
begin
|
||||||
|
if get_enum_init_val_ref(t,eleref) then
|
||||||
|
begin
|
||||||
|
a_load_ref_stack(list,java_jlobject,eleref,prepare_stack_for_ref(list,eleref,false));
|
||||||
|
g_call_system_proc(list,'fpc_initialize_array_object');
|
||||||
|
end;
|
||||||
|
end
|
||||||
else
|
else
|
||||||
internalerror(2011031901);
|
internalerror(2011031901);
|
||||||
end;
|
end;
|
||||||
@ -1933,11 +1954,35 @@ implementation
|
|||||||
tg.ungettemp(list,tmpref);
|
tg.ungettemp(list,tmpref);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure thlcgjvm.allocate_enum_with_base_ref(list: TAsmList; vs: tabstractvarsym; const initref: treference; destbaseref: treference);
|
||||||
|
begin
|
||||||
|
destbaseref.symbol:=current_asmdata.RefAsmSymbol(vs.mangledname);
|
||||||
|
{ only copy the reference, not the actual data }
|
||||||
|
a_load_ref_ref(list,java_jlobject,java_jlobject,initref,destbaseref);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function thlcgjvm.get_enum_init_val_ref(def: tdef; out ref: treference): boolean;
|
||||||
|
var
|
||||||
|
sym: tstaticvarsym;
|
||||||
|
begin
|
||||||
|
result:=false;
|
||||||
|
sym:=tstaticvarsym(tenumdef(def).getbasedef.classdef.symtable.Find('__FPC_ZERO_INITIALIZER'));
|
||||||
|
{ no enum with ordinal value 0 -> exit }
|
||||||
|
if not assigned(sym) then
|
||||||
|
exit;
|
||||||
|
reference_reset_symbol(ref,current_asmdata.RefAsmSymbol(sym.mangledname),0,4);
|
||||||
|
result:=true;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure thlcgjvm.allocate_implicit_structs_for_st_with_base_ref(list: TAsmList; st: tsymtable; const ref: treference; allocvartyp: tsymtyp);
|
procedure thlcgjvm.allocate_implicit_structs_for_st_with_base_ref(list: TAsmList; st: tsymtable; const ref: treference; allocvartyp: tsymtyp);
|
||||||
var
|
var
|
||||||
vs: tabstractvarsym;
|
vs: tabstractvarsym;
|
||||||
def: tdef;
|
def: tdef;
|
||||||
i: longint;
|
i: longint;
|
||||||
|
initref: treference;
|
||||||
begin
|
begin
|
||||||
for i:=0 to st.symlist.count-1 do
|
for i:=0 to st.symlist.count-1 do
|
||||||
begin
|
begin
|
||||||
@ -1951,9 +1996,16 @@ implementation
|
|||||||
intialising the constant }
|
intialising the constant }
|
||||||
if [vo_is_external,vo_has_local_copy]*vs.varoptions=[vo_is_external] then
|
if [vo_is_external,vo_has_local_copy]*vs.varoptions=[vo_is_external] then
|
||||||
continue;
|
continue;
|
||||||
if not jvmimplicitpointertype(vs.vardef) then
|
if jvmimplicitpointertype(vs.vardef) then
|
||||||
continue;
|
allocate_implicit_struct_with_base_ref(list,vs,ref)
|
||||||
allocate_implicit_struct_with_base_ref(list,vs,ref);
|
{ enums are class instances in Java, while they are ordinals in
|
||||||
|
Pascal. When they are initialized with enum(0), such as in
|
||||||
|
constructors or global variables, initialize them with the
|
||||||
|
enum instance for 0 if it exists (if not, it remains nil since
|
||||||
|
there is no valid enum value in it) }
|
||||||
|
else if (vs.vardef.typ=enumdef) and
|
||||||
|
get_enum_init_val_ref(vs.vardef,initref) then
|
||||||
|
allocate_enum_with_base_ref(list,vs,initref,ref);
|
||||||
end;
|
end;
|
||||||
{ process symtables of routines part of this symtable (for local typed
|
{ process symtables of routines part of this symtable (for local typed
|
||||||
constants) }
|
constants) }
|
||||||
@ -1978,6 +2030,7 @@ implementation
|
|||||||
|
|
||||||
procedure thlcgjvm.gen_initialize_fields_code(list: TAsmList);
|
procedure thlcgjvm.gen_initialize_fields_code(list: TAsmList);
|
||||||
var
|
var
|
||||||
|
sym: tsym;
|
||||||
selfpara: tparavarsym;
|
selfpara: tparavarsym;
|
||||||
selfreg: tregister;
|
selfreg: tregister;
|
||||||
ref: treference;
|
ref: treference;
|
||||||
@ -1989,12 +2042,17 @@ implementation
|
|||||||
{ check whether there are any fields that need initialisation }
|
{ check whether there are any fields that need initialisation }
|
||||||
needinit:=false;
|
needinit:=false;
|
||||||
for i:=0 to obj.symtable.symlist.count-1 do
|
for i:=0 to obj.symtable.symlist.count-1 do
|
||||||
if (tsym(obj.symtable.symlist[i]).typ=fieldvarsym) and
|
begin
|
||||||
jvmimplicitpointertype(tfieldvarsym(obj.symtable.symlist[i]).vardef) then
|
sym:=tsym(obj.symtable.symlist[i]);
|
||||||
begin
|
if (sym.typ=fieldvarsym) and
|
||||||
needinit:=true;
|
(jvmimplicitpointertype(tfieldvarsym(sym).vardef) or
|
||||||
break;
|
((tfieldvarsym(sym).vardef.typ=enumdef) and
|
||||||
end;
|
get_enum_init_val_ref(tfieldvarsym(sym).vardef,ref))) then
|
||||||
|
begin
|
||||||
|
needinit:=true;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
if not needinit then
|
if not needinit then
|
||||||
exit;
|
exit;
|
||||||
selfpara:=tparavarsym(current_procinfo.procdef.parast.find('self'));
|
selfpara:=tparavarsym(current_procinfo.procdef.parast.find('self'));
|
||||||
|
@ -101,7 +101,6 @@ implementation
|
|||||||
basedef: tenumdef;
|
basedef: tenumdef;
|
||||||
sym: tenumsym;
|
sym: tenumsym;
|
||||||
classfield: tsym;
|
classfield: tsym;
|
||||||
i: longint;
|
|
||||||
begin
|
begin
|
||||||
if (resultdef.typ<>enumdef) or
|
if (resultdef.typ<>enumdef) or
|
||||||
enumconstok then
|
enumconstok then
|
||||||
@ -113,20 +112,15 @@ implementation
|
|||||||
{ a) find the enumsym corresponding to the value (may not exist in case
|
{ a) find the enumsym corresponding to the value (may not exist in case
|
||||||
of an explicit typecast of an integer -> error) }
|
of an explicit typecast of an integer -> error) }
|
||||||
sym:=nil;
|
sym:=nil;
|
||||||
basedef:=tenumdef(resultdef).getbasedef;
|
sym:=tenumsym(tenumdef(resultdef).int2enumsym(int64(value)));
|
||||||
for i:=0 to tenumdef(resultdef).symtable.symlist.count-1 do
|
|
||||||
begin
|
|
||||||
sym:=tenumsym(basedef.symtable.symlist[i]);
|
|
||||||
if sym.value=value then
|
|
||||||
break;
|
|
||||||
sym:=nil;
|
|
||||||
end;
|
|
||||||
if not assigned(sym) then
|
if not assigned(sym) then
|
||||||
begin
|
begin
|
||||||
Message(parser_e_range_check_error);
|
Message(parser_e_range_check_error);
|
||||||
|
result:=nil;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
{ b) find the corresponding class field }
|
{ b) find the corresponding class field }
|
||||||
|
basedef:=tenumdef(resultdef).getbasedef;
|
||||||
classfield:=search_struct_member(basedef.classdef,sym.name);
|
classfield:=search_struct_member(basedef.classdef,sym.name);
|
||||||
|
|
||||||
{ c) create loadnode of the field }
|
{ c) create loadnode of the field }
|
||||||
|
@ -270,7 +270,8 @@ implementation
|
|||||||
pd: tprocdef;
|
pd: tprocdef;
|
||||||
old_current_structdef: tabstractrecorddef;
|
old_current_structdef: tabstractrecorddef;
|
||||||
i: longint;
|
i: longint;
|
||||||
sym: tstaticvarsym;
|
sym,
|
||||||
|
aliassym: tstaticvarsym;
|
||||||
fsym: tfieldvarsym;
|
fsym: tfieldvarsym;
|
||||||
sstate: tscannerstate;
|
sstate: tscannerstate;
|
||||||
sl: tpropaccesslist;
|
sl: tpropaccesslist;
|
||||||
@ -333,6 +334,14 @@ implementation
|
|||||||
fsym:=tfieldvarsym.create(tenumsym(tenumdef(def).symtable.symlist[i]).realname,vs_final,enumclass,[]);
|
fsym:=tfieldvarsym.create(tenumsym(tenumdef(def).symtable.symlist[i]).realname,vs_final,enumclass,[]);
|
||||||
enumclass.symtable.insert(fsym);
|
enumclass.symtable.insert(fsym);
|
||||||
sym:=make_field_static(enumclass.symtable,fsym);
|
sym:=make_field_static(enumclass.symtable,fsym);
|
||||||
|
{ add alias for the field representing ordinal(0), for use in
|
||||||
|
initialization code }
|
||||||
|
if tenumsym(tenumdef(def).symtable.symlist[i]).value=0 then
|
||||||
|
begin
|
||||||
|
aliassym:=tstaticvarsym.create('__FPC_Zero_Initializer',vs_final,enumclass,[vo_is_external]);
|
||||||
|
enumclass.symtable.insert(aliassym);
|
||||||
|
aliassym.set_raw_mangledname(sym.mangledname);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
{ create local "array of enumtype" type for the "values" functionality
|
{ create local "array of enumtype" type for the "values" functionality
|
||||||
(used internally by the JDK) }
|
(used internally by the JDK) }
|
||||||
|
@ -737,6 +737,7 @@ interface
|
|||||||
function min:asizeint;
|
function min:asizeint;
|
||||||
function max:asizeint;
|
function max:asizeint;
|
||||||
function getfirstsym:tsym;
|
function getfirstsym:tsym;
|
||||||
|
function int2enumsym(l: asizeint): tsym;
|
||||||
{ returns basedef if assigned, otherwise self }
|
{ returns basedef if assigned, otherwise self }
|
||||||
function getbasedef: tenumdef;
|
function getbasedef: tenumdef;
|
||||||
end;
|
end;
|
||||||
@ -1895,6 +1896,30 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function tenumdef.int2enumsym(l: asizeint): tsym;
|
||||||
|
var
|
||||||
|
i: longint;
|
||||||
|
sym: tsym;
|
||||||
|
bdef: tenumdef;
|
||||||
|
begin
|
||||||
|
result:=nil;
|
||||||
|
if (l<minval) or
|
||||||
|
(l>maxval) then
|
||||||
|
exit;
|
||||||
|
bdef:=getbasedef;
|
||||||
|
for i:=0 to bdef.symtable.symlist.count-1 do
|
||||||
|
begin
|
||||||
|
sym:=tsym(bdef.symtable.symlist[i]);
|
||||||
|
if (sym.typ=enumsym) and
|
||||||
|
(tenumsym(sym).value=l) then
|
||||||
|
begin
|
||||||
|
result:=sym;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function tenumdef.getbasedef: tenumdef;
|
function tenumdef.getbasedef: tenumdef;
|
||||||
begin
|
begin
|
||||||
if not assigned(basedef) then
|
if not assigned(basedef) then
|
||||||
|
@ -227,6 +227,7 @@ interface
|
|||||||
function mangledname:TSymStr;override;
|
function mangledname:TSymStr;override;
|
||||||
procedure set_mangledbasename(const s: TSymStr);
|
procedure set_mangledbasename(const s: TSymStr);
|
||||||
procedure set_mangledname(const s:TSymStr);
|
procedure set_mangledname(const s:TSymStr);
|
||||||
|
procedure set_raw_mangledname(const s:TSymStr);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
tabsolutevarsym = class(tabstractvarsym)
|
tabsolutevarsym = class(tabstractvarsym)
|
||||||
@ -1623,6 +1624,18 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure tstaticvarsym.set_raw_mangledname(const s: TSymStr);
|
||||||
|
begin
|
||||||
|
{$ifndef symansistr}
|
||||||
|
stringdispose(_mangledname);
|
||||||
|
_mangledname:=stringdup(s);
|
||||||
|
{$else}
|
||||||
|
_mangledname:=s;
|
||||||
|
{$endif}
|
||||||
|
include(varoptions,vo_has_mangledname);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{****************************************************************************
|
{****************************************************************************
|
||||||
TLOCALVARSYM
|
TLOCALVARSYM
|
||||||
****************************************************************************}
|
****************************************************************************}
|
||||||
|
@ -637,6 +637,7 @@ procedure fpc_initialize_array_record(arr: TJObjectArray; normalarrdim: longint;
|
|||||||
procedure fpc_initialize_array_procvar(arr: TJObjectArray; normalarrdim: longint; inst: FpcBaseProcVarType);compilerproc;
|
procedure fpc_initialize_array_procvar(arr: TJObjectArray; normalarrdim: longint; inst: FpcBaseProcVarType);compilerproc;
|
||||||
procedure fpc_initialize_array_bitset(arr: TJObjectArray; normalarrdim: longint; inst: FpcBitSet);compilerproc;
|
procedure fpc_initialize_array_bitset(arr: TJObjectArray; normalarrdim: longint; inst: FpcBitSet);compilerproc;
|
||||||
procedure fpc_initialize_array_enumset(arr: TJObjectArray; normalarrdim: longint; inst: JUEnumSet);compilerproc;
|
procedure fpc_initialize_array_enumset(arr: TJObjectArray; normalarrdim: longint; inst: JUEnumSet);compilerproc;
|
||||||
|
procedure fpc_initialize_array_object(arr: TJObjectArray; normalarrdim: longint; inst: JLObject);compilerproc;
|
||||||
procedure fpc_initialize_array_shortstring(arr: TJObjectArray; normalarrdim: longint; maxlen: byte);compilerproc;
|
procedure fpc_initialize_array_shortstring(arr: TJObjectArray; normalarrdim: longint; maxlen: byte);compilerproc;
|
||||||
|
|
||||||
{ set helpers }
|
{ set helpers }
|
||||||
|
@ -148,6 +148,27 @@ procedure fpc_initialize_array_enumset(arr: TJObjectArray; normalarrdim: longint
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{ initialize entire array with the same object, without making copies. Used for
|
||||||
|
initialization with enum instance }
|
||||||
|
procedure fpc_initialize_array_object_intern(arr: TJObjectArray; normalarrdim: longint; inst: JLObject); external name 'fpc_initialize_array_object';
|
||||||
|
|
||||||
|
procedure fpc_initialize_array_object(arr: TJObjectArray; normalarrdim: longint; inst: JLObject);compilerproc;
|
||||||
|
var
|
||||||
|
i: longint;
|
||||||
|
begin
|
||||||
|
if normalarrdim > 0 then
|
||||||
|
begin
|
||||||
|
for i:=low(arr) to high(arr) do
|
||||||
|
fpc_initialize_array_object_intern(TJObjectArray(arr[i]),normalarrdim-1,inst);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
for i:=low(arr) to high(arr) do
|
||||||
|
arr[i]:=inst;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure fpc_initialize_array_shortstring_intern(arr: TJObjectArray; normalarrdim: longint; maxlen: byte); external name 'fpc_initialize_array_shortstring';
|
procedure fpc_initialize_array_shortstring_intern(arr: TJObjectArray; normalarrdim: longint; maxlen: byte); external name 'fpc_initialize_array_shortstring';
|
||||||
|
|
||||||
procedure fpc_initialize_array_shortstring(arr: TJObjectArray; normalarrdim: longint; maxlen: byte);compilerproc;
|
procedure fpc_initialize_array_shortstring(arr: TJObjectArray; normalarrdim: longint; maxlen: byte);compilerproc;
|
||||||
|
Loading…
Reference in New Issue
Block a user