* fixed typecasting to/from classrefdef

git-svn-id: branches/jvmbackend@18558 -
This commit is contained in:
Jonas Maebe 2011-08-20 08:10:16 +00:00
parent 84640fe7f0
commit b370314194

View File

@ -62,10 +62,16 @@ interface
tjvmasnode = class(tcgasnode)
protected
{ to discern beween "obj as tclassref" and "tclassref(obj)" }
classreftypecast: boolean;
function target_specific_typecheck: boolean;override;
public
function pass_1 : tnode;override;
procedure pass_generate_code; override;
function dogetcopy: tnode; override;
function docompare(p: tnode): boolean; override;
constructor ppuload(t: tnodetype; ppufile: tcompilerppufile); override;
procedure ppuwrite(ppufile: tcompilerppufile); override;
end;
tjvmisnode = class(tisnode)
@ -445,6 +451,8 @@ implementation
fromdef:=tarraydef(fromdef).elementdef;
todef:=tarraydef(todef).elementdef;
end;
fromdef:=maybe_find_real_class_definition(fromdef,false);
todef:=maybe_find_real_class_definition(todef,false);
end;
@ -486,8 +494,7 @@ implementation
toclasscompatible,
procvarconv: boolean;
fromdef,
todef,
jlclass: tdef;
todef: tdef;
fromarrtype,
toarrtype: char;
begin
@ -503,13 +510,13 @@ implementation
fromclasscompatible:=
(left.resultdef.typ=objectdef) or
is_dynamic_array(left.resultdef) or
((left.resultdef.typ in [recorddef,stringdef]) and
((left.resultdef.typ in [recorddef,stringdef,classrefdef]) and
(resultdef.typ=objectdef)) or
procvarconv;
toclasscompatible:=
(resultdef.typ=objectdef) or
is_dynamic_array(resultdef) or
((resultdef.typ in [recorddef,stringdef]) and
((resultdef.typ in [recorddef,stringdef,classrefdef]) and
(left.resultdef.typ=objectdef)) or
procvarconv;
if fromclasscompatible and toclasscompatible then
@ -523,6 +530,8 @@ implementation
* related to source
* a primitive that are represented by the same type in Java
(e.g., byte and shortint) }
{ in case of arrays, check the compatibility of the innermost types }
fromdef:=left.resultdef;
todef:=resultdef;
get_most_nested_types(fromdef,todef);
@ -532,7 +541,10 @@ implementation
not fromdef.is_related(todef) and
(todef<>java_jlobject) and
((fromarrtype in ['A','R']) or
(fromarrtype<>toarrtype)) then
(fromarrtype<>toarrtype)) and
((fromdef.typ<>classrefdef) or
(todef.typ<>classrefdef) or
not tclassrefdef(fromdef).pointeddef.is_related(tclassrefdef(todef).pointeddef)) then
begin
if not check_only and
not assignment_side then
@ -541,6 +553,8 @@ implementation
if resultdef.typ=objectdef then
resnode:=cloadvmtaddrnode.create(resnode);
resnode:=casnode.create(left,resnode);
if resultdef.typ=classrefdef then
tjvmasnode(resnode).classreftypecast:=true;
left:=nil;
end
end
@ -553,31 +567,6 @@ implementation
exit;
end;
{ from classrefdef to JLClass and JLObject and back }
if (left.resultdef.typ=classrefdef) or
(resultdef.typ=classrefdef) then
begin
if (left.resultdef.typ=classrefdef) and
(resultdef.typ=classrefdef) then
begin
if not tclassrefdef(left.resultdef).pointeddef.is_related(resultdef) and
not tclassrefdef(resultdef).pointeddef.is_related(left.resultdef) then
CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename);
end
else
begin
jlclass:=search_system_type('JLCLASS').typedef;
if (left.resultdef<>jlclass) and
(left.resultdef<>java_jlobject) and
(resultdef<>jlclass) and
(resultdef<>java_jlobject) then
CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename);
end;
result:=true;
exit;
end;
{ don't allow conversions between different classes of primitive types,
except for a few special cases }
@ -748,20 +737,67 @@ implementation
result:=false;
end;
function isclassrefconv(fromdef, todef: tdef): boolean;
var
jlclass: tdef;
begin
jlclass:=nil;
if fromdef.typ=classrefdef then
begin
result:=todef=java_jlobject;
if not result and
(todef.typ=classrefdef) then
{ the fromdef.is_related(todef) case should not become an as-node,
handled in typeconversion itself and ignored since always ok
-- this one is not very useful either since everything is plain
JLClass anyway, but maybe in the future it will be different }
result:=tclassrefdef(todef).pointeddef.is_related(tclassrefdef(fromdef).pointeddef);
if not result then
begin
jlclass:=search_system_type('JLCLASS').typedef;
result:=todef=jlclass;
end;
end
else if todef.typ=classrefdef then
begin
result:=fromdef=java_jlobject;
if not result then
begin
jlclass:=search_system_type('JLCLASS').typedef;
result:=fromdef=jlclass;
end;
end
else
result:=false;
end;
var
fromelt, toelt: tdef;
realfromdef,
realtodef: tdef;
begin
if is_java_class_or_interface(node.left.resultdef) and
(node.right.resultdef.typ=classrefdef) and
((node.nodetype<>asn) or
not tjvmasnode(node).classreftypecast) then
begin
{ handle using normal code }
result:=false;
exit;
end;
realfromdef:=maybe_find_real_class_definition(node.left.resultdef,false);
realtodef:=node.right.resultdef;
if realtodef.typ=classrefdef then
if (realtodef.typ=classrefdef) and
((node.nodetype<>asn) or
not tjvmasnode(node).classreftypecast) then
realtodef:=tclassrefdef(realtodef).pointeddef;
realtodef:=maybe_find_real_class_definition(realtodef,false);
result:=isrecordconv(realfromdef,realtodef);
if not result then
result:=isstringconv(realfromdef,realtodef);
if not result then
result:=isclassrefconv(realfromdef,realtodef);
if not result then
{ dynamic arrays can be converted to java.lang.Object and vice versa }
if realtodef=java_jlobject then
@ -786,22 +822,10 @@ implementation
(fromelt.typ=arraydef)) and
((toelt.typ=objectdef) or
(toelt.typ=arraydef)));
end
else
begin
if (node.right.resultdef.typ<>classrefdef) then
result:=false
else
result:=true;
end;
if result then
if node.nodetype=asn then
begin
if realtodef.typ<>classrefdef then
node.resultdef:=realtodef
else
node.resultdef:=tclassrefdef(realtodef).pointeddef
end
node.resultdef:=realtodef
else
node.resultdef:=pasbool8type;
end;
@ -885,6 +909,8 @@ implementation
checkdef:=java_jlstring;
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))));
location_reset(node.location,LOC_REGISTER,OS_ADDR);
@ -915,6 +941,35 @@ implementation
end;
function tjvmasnode.dogetcopy: tnode;
begin
result:=inherited dogetcopy;
tjvmasnode(result).classreftypecast:=classreftypecast;
end;
function tjvmasnode.docompare(p: tnode): boolean;
begin
result:=
inherited docompare(p) and
(tjvmasnode(p).classreftypecast=classreftypecast);
end;
constructor tjvmasnode.ppuload(t: tnodetype; ppufile: tcompilerppufile);
begin
inherited;
classreftypecast:=boolean(ppufile.getbyte);
end;
procedure tjvmasnode.ppuwrite(ppufile: tcompilerppufile);
begin
inherited ppuwrite(ppufile);
ppufile.putbyte(byte(classreftypecast));
end;
{*****************************************************************************
TJVMIsNode
*****************************************************************************}