mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-01 16:29:39 +01:00
* generalized handling of pointers to non-implicit pointer types:
as far as Java is concerned, they're now all arrays of JLObject.
When loading a value from them, we typecast the loaded value
to the appropriate type. This allows typecasting one pointer
type to another without getting verification errors (since an
"array of JLObject" is not compatible with "array of JLString")
- no longer allow dereferencing untyped pointers on the JVM
target, since that always results in invalid bytecode
git-svn-id: branches/jvmbackend@18819 -
This commit is contained in:
parent
0364b7acf9
commit
992cc352c6
@ -69,6 +69,7 @@ unit cgutils;
|
||||
indexbase: tregister;
|
||||
indexsymbol: tasmsymbol;
|
||||
indexoffset: aint;
|
||||
checkcast: boolean;
|
||||
{$endif jvm}
|
||||
alignment : byte;
|
||||
end;
|
||||
|
||||
@ -154,6 +154,8 @@ uses
|
||||
property maxevalstackheight: longint read fmaxevalstackheight;
|
||||
|
||||
procedure gen_initialize_fields_code(list:TAsmList);
|
||||
|
||||
procedure gen_typecheck(list: TAsmList; checkop: tasmop; checkdef: tdef);
|
||||
protected
|
||||
function get_enum_init_val_ref(def: tdef; out ref: treference): boolean;
|
||||
|
||||
@ -1778,6 +1780,8 @@ implementation
|
||||
incstack(list,1+ord(size.size>4)-extra_slots);
|
||||
if finishandval<>-1 then
|
||||
a_op_const_stack(list,OP_AND,size,finishandval);
|
||||
if ref.checkcast then
|
||||
gen_typecheck(list,a_checkcast,size);
|
||||
end;
|
||||
|
||||
function thlcgjvm.loadstoreopcref(def: tdef; isload: boolean; const ref: treference; out finishandval: aint): tasmop;
|
||||
@ -2089,6 +2093,40 @@ implementation
|
||||
allocate_implicit_structs_for_st_with_base_ref(list,obj.symtable,ref,fieldvarsym);
|
||||
end;
|
||||
|
||||
procedure thlcgjvm.gen_typecheck(list: TAsmList; checkop: tasmop; checkdef: tdef);
|
||||
begin
|
||||
{ replace special types with their equivalent class type }
|
||||
if (checkdef.typ=pointerdef) and
|
||||
jvmimplicitpointertype(tpointerdef(checkdef).pointeddef) then
|
||||
checkdef:=tpointerdef(checkdef).pointeddef;
|
||||
if (checkdef=voidpointertype) or
|
||||
(checkdef.typ=formaldef) then
|
||||
checkdef:=java_jlobject
|
||||
else if checkdef.typ=enumdef then
|
||||
checkdef:=tenumdef(checkdef).classdef
|
||||
else if checkdef.typ=setdef then
|
||||
begin
|
||||
if tsetdef(checkdef).elementdef.typ=enumdef then
|
||||
checkdef:=java_juenumset
|
||||
else
|
||||
checkdef:=java_jubitset;
|
||||
end
|
||||
else if checkdef.typ=procvardef then
|
||||
checkdef:=tprocvardef(checkdef).classdef
|
||||
else if is_wide_or_unicode_string(checkdef) then
|
||||
checkdef:=java_jlstring
|
||||
else if is_ansistring(checkdef) then
|
||||
checkdef:=java_ansistring
|
||||
else if is_shortstring(checkdef) then
|
||||
checkdef:=java_shortstring;
|
||||
if checkdef.typ in [objectdef,recorddef] then
|
||||
list.concat(taicpu.op_sym(checkop,current_asmdata.RefAsmSymbol(tabstractrecorddef(checkdef).jvm_full_typename(true))))
|
||||
else if checkdef.typ=classrefdef then
|
||||
list.concat(taicpu.op_sym(checkop,current_asmdata.RefAsmSymbol('java/lang/Class')))
|
||||
else
|
||||
list.concat(taicpu.op_sym(checkop,current_asmdata.RefAsmSymbol(jvmencodetype(checkdef,false))));
|
||||
end;
|
||||
|
||||
procedure thlcgjvm.resizestackfpuval(list: TAsmList; fromsize, tosize: tcgsize);
|
||||
begin
|
||||
if (fromsize=OS_F32) and
|
||||
|
||||
@ -253,15 +253,24 @@ implementation
|
||||
end;
|
||||
pointerdef :
|
||||
begin
|
||||
if def=voidpointertype then
|
||||
if is_voidpointer(def) then
|
||||
result:=jvmaddencodedtype(java_jlobject,false,encodedstr,forcesignature,founderror)
|
||||
else if tpointerdef(def).pointeddef.typ in [orddef,floatdef] then
|
||||
begin
|
||||
encodedstr:=encodedstr+'[';
|
||||
result:=jvmaddencodedtype(tpointerdef(def).pointeddef,false,encodedstr,forcesignature,founderror);
|
||||
end
|
||||
else if jvmimplicitpointertype(tpointerdef(def).pointeddef) then
|
||||
result:=jvmaddencodedtype(tpointerdef(def).pointeddef,false,encodedstr,forcesignature,founderror)
|
||||
else
|
||||
begin
|
||||
{ used for internal pointer constructs }
|
||||
{ Semantically, these are pointers to types that are
|
||||
pointer-based themselves (or typecastable to pointer).
|
||||
Internally, we represent them all as array of JLObject so that
|
||||
they are assignment-compatible. We will perform the type
|
||||
checks when actually loading a value from them }
|
||||
encodedstr:=encodedstr+'[';
|
||||
result:=jvmaddencodedtype(tpointerdef(def).pointeddef,false,encodedstr,forcesignature,founderror);
|
||||
result:=jvmaddencodedtype(java_jlobject,false,encodedstr,forcesignature,founderror)
|
||||
end;
|
||||
end;
|
||||
floatdef :
|
||||
|
||||
@ -1485,36 +1485,7 @@ implementation
|
||||
checkdef:=tclassrefdef(node.right.resultdef).pointeddef
|
||||
else
|
||||
checkdef:=node.right.resultdef;
|
||||
{ replace special types with their equivalent class type }
|
||||
if (checkdef.typ=pointerdef) and
|
||||
jvmimplicitpointertype(tpointerdef(checkdef).pointeddef) then
|
||||
checkdef:=tpointerdef(checkdef).pointeddef;
|
||||
if (checkdef=voidpointertype) or
|
||||
(checkdef.typ=formaldef) then
|
||||
checkdef:=java_jlobject
|
||||
else if checkdef.typ=enumdef then
|
||||
checkdef:=tenumdef(checkdef).classdef
|
||||
else if checkdef.typ=setdef then
|
||||
begin
|
||||
if tsetdef(checkdef).elementdef.typ=enumdef then
|
||||
checkdef:=java_juenumset
|
||||
else
|
||||
checkdef:=java_jubitset;
|
||||
end
|
||||
else if checkdef.typ=procvardef then
|
||||
checkdef:=tprocvardef(checkdef).classdef
|
||||
else if is_wide_or_unicode_string(checkdef) then
|
||||
checkdef:=java_jlstring
|
||||
else if is_ansistring(checkdef) then
|
||||
checkdef:=java_ansistring
|
||||
else if is_shortstring(checkdef) then
|
||||
checkdef:=java_shortstring;
|
||||
if checkdef.typ in [objectdef,recorddef] then
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(tabstractrecorddef(checkdef).jvm_full_typename(true))))
|
||||
else if checkdef.typ=classrefdef then
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol('java/lang/Class')))
|
||||
else
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(jvmencodetype(checkdef,false))));
|
||||
thlcgjvm(hlcg).gen_typecheck(current_asmdata.CurrAsmList,opcode,checkdef);
|
||||
location_reset(node.location,LOC_REGISTER,OS_ADDR);
|
||||
node.location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,node.resultdef);
|
||||
thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,node.resultdef,node.location.register);
|
||||
|
||||
@ -41,6 +41,7 @@ interface
|
||||
end;
|
||||
|
||||
tjvmderefnode = class(tcgderefnode)
|
||||
function pass_typecheck: tnode; override;
|
||||
procedure pass_generate_code; override;
|
||||
end;
|
||||
|
||||
@ -68,12 +69,25 @@ implementation
|
||||
TJVMDEREFNODE
|
||||
*****************************************************************************}
|
||||
|
||||
function tjvmderefnode.pass_typecheck: tnode;
|
||||
begin
|
||||
result:=inherited pass_typecheck;
|
||||
if assigned(result) then
|
||||
exit;
|
||||
{ don't allow dereferencing untyped pointers, because how this has to
|
||||
be done depends on whether it's a pointer to an implicit pointer type
|
||||
or not }
|
||||
if is_voidpointer(left.resultdef) then
|
||||
CGMessage(parser_e_illegal_expression);
|
||||
end;
|
||||
|
||||
|
||||
procedure tjvmderefnode.pass_generate_code;
|
||||
var
|
||||
implicitptr: boolean;
|
||||
begin
|
||||
secondpass(left);
|
||||
implicitptr:=jvmimplicitpointertype(tpointerdef(left.resultdef).pointeddef);
|
||||
implicitptr:=jvmimplicitpointertype(resultdef);
|
||||
if implicitptr then
|
||||
begin
|
||||
{ this is basically a typecast: the left node is a regular
|
||||
@ -91,11 +105,18 @@ implementation
|
||||
else
|
||||
begin
|
||||
{ these are always arrays (used internally for pointers to var
|
||||
parameters stored in nestedfpstructs) }
|
||||
parameters stored in nestedfpstructs, and by programmers for any
|
||||
kind of pointers) }
|
||||
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
|
||||
location_reset_ref(location,LOC_REFERENCE,def_cgsize(resultdef),4);
|
||||
reference_reset_base(location.reference,left.location.register,0,4);
|
||||
location.reference.arrayreftype:=art_indexconst;
|
||||
if (left.nodetype<>addrn) and
|
||||
not(resultdef.typ in [orddef,floatdef]) and
|
||||
not is_voidpointer(resultdef) and
|
||||
((resultdef.typ<>objectdef) or
|
||||
(find_real_class_definition(tobjectdef(resultdef),false)<>java_jlobject)) then
|
||||
location.reference.checkcast:=true;
|
||||
end
|
||||
end;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user