mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-29 23:00:13 +02:00
* generate a loadvmtaddrnode wrapper around Java objectdef typenode arguments
to tasnode (like for regular Object Pascal classes) * don't collect WPO information for Java classes in tloadvmtaddrnode.pass_1() (devirtualization can't work for Java, since classes can always be loaded at run time, except for final/sealed classes -- but that's not yet implemented) + JVM is-node support, unified JVM type checking codegen for is- and as-nodes git-svn-id: branches/jvmbackend@18383 -
This commit is contained in:
parent
c1abc4a275
commit
fde622e050
@ -62,6 +62,14 @@ interface
|
|||||||
procedure pass_generate_code; override;
|
procedure pass_generate_code; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
tjvmisnode = class(tisnode)
|
||||||
|
protected
|
||||||
|
function target_specific_typecheck: boolean;override;
|
||||||
|
public
|
||||||
|
function pass_1 : tnode;override;
|
||||||
|
procedure pass_generate_code; override;
|
||||||
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
@ -420,7 +428,10 @@ implementation
|
|||||||
not is_dynamic_array(fromdef)) or
|
not is_dynamic_array(fromdef)) or
|
||||||
(todef<>java_jlobject) then
|
(todef<>java_jlobject) then
|
||||||
begin
|
begin
|
||||||
result:=casnode.create(left,ctypenode.create(resultdef));
|
result:=ctypenode.create(resultdef);
|
||||||
|
if resultdef.typ=objectdef then
|
||||||
|
result:=cloadvmtaddrnode.create(result);
|
||||||
|
result:=casnode.create(left,result);
|
||||||
left:=nil;
|
left:=nil;
|
||||||
end;
|
end;
|
||||||
exit;
|
exit;
|
||||||
@ -462,30 +473,31 @@ implementation
|
|||||||
CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename);
|
CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
{*****************************************************************************
|
{*****************************************************************************
|
||||||
TJVMAsNode
|
AsNode and IsNode common helpers
|
||||||
*****************************************************************************}
|
*****************************************************************************}
|
||||||
|
|
||||||
function tjvmasnode.target_specific_typecheck: boolean;
|
function asis_target_specific_typecheck(node: tasisnode): boolean;
|
||||||
var
|
var
|
||||||
fromelt, toelt: tdef;
|
fromelt, toelt: tdef;
|
||||||
begin
|
begin
|
||||||
{ dynamic arrays can be converted to java.lang.Object and vice versa }
|
{ dynamic arrays can be converted to java.lang.Object and vice versa }
|
||||||
if right.resultdef=java_jlobject then
|
if node.right.resultdef=java_jlobject then
|
||||||
{ dynamic array to java.lang.Object }
|
{ dynamic array to java.lang.Object }
|
||||||
result:=is_dynamic_array(left.resultdef)
|
result:=is_dynamic_array(node.left.resultdef)
|
||||||
else if is_dynamic_array(right.resultdef) then
|
else if is_dynamic_array(node.right.resultdef) then
|
||||||
begin
|
begin
|
||||||
{ <x> to dynamic array: only if possibly valid }
|
{ <x> to dynamic array: only if possibly valid }
|
||||||
fromelt:=left.resultdef;
|
fromelt:=node.left.resultdef;
|
||||||
toelt:=right.resultdef;
|
toelt:=node.right.resultdef;
|
||||||
get_most_nested_types(fromelt,toelt);
|
get_most_nested_types(fromelt,toelt);
|
||||||
{ final levels must be convertable:
|
{ final levels must be convertable:
|
||||||
a) from dynarray to java.lang.Object or vice versa, or
|
a) from dynarray to java.lang.Object or vice versa, or
|
||||||
b) the same primitive/class type
|
b) the same primitive/class type
|
||||||
}
|
}
|
||||||
result:=
|
result:=
|
||||||
(compare_defs(fromelt,toelt,left.nodetype) in [te_exact,te_equal]) or
|
(compare_defs(fromelt,toelt,node.left.nodetype) in [te_exact,te_equal]) or
|
||||||
(((fromelt.typ=objectdef) or
|
(((fromelt.typ=objectdef) or
|
||||||
is_dynamic_array(fromelt)) and
|
is_dynamic_array(fromelt)) and
|
||||||
((toelt.typ=objectdef) or
|
((toelt.typ=objectdef) or
|
||||||
@ -495,12 +507,58 @@ implementation
|
|||||||
begin
|
begin
|
||||||
{ full class reference support requires using the Java reflection API,
|
{ full class reference support requires using the Java reflection API,
|
||||||
not yet implemented }
|
not yet implemented }
|
||||||
if (right.nodetype<>typen) then
|
if (node.right.nodetype<>loadvmtaddrn) or
|
||||||
|
(tloadvmtaddrnode(node.right).left.nodetype<>typen) then
|
||||||
internalerror(2011012601);
|
internalerror(2011012601);
|
||||||
result:=false;
|
result:=false;
|
||||||
end;
|
end;
|
||||||
if result then
|
if result then
|
||||||
resultdef:=right.resultdef;
|
if node.nodetype=asn then
|
||||||
|
begin
|
||||||
|
if node.right.resultdef.typ<>classrefdef then
|
||||||
|
node.resultdef:=node.right.resultdef
|
||||||
|
else
|
||||||
|
node.resultdef:=tclassrefdef(node.right.resultdef).pointeddef
|
||||||
|
end
|
||||||
|
else
|
||||||
|
node.resultdef:=pasbool8type;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure asis_generate_code(node: tasisnode; opcode: tasmop);
|
||||||
|
var
|
||||||
|
checkdef: tdef;
|
||||||
|
begin
|
||||||
|
secondpass(node.left);
|
||||||
|
thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,node.left.resultdef,node.left.location);
|
||||||
|
location_freetemp(current_asmdata.CurrAsmList,node.left.location);
|
||||||
|
{ Perform a checkcast instruction, which will raise an exception in case
|
||||||
|
the actual type does not match/inherit from the expected type.
|
||||||
|
|
||||||
|
Object types need the full type name (package+class name), arrays only
|
||||||
|
the array definition }
|
||||||
|
if node.nodetype=asn then
|
||||||
|
checkdef:=node.resultdef
|
||||||
|
else if node.right.resultdef.typ=classrefdef then
|
||||||
|
checkdef:=tclassrefdef(node.right.resultdef).pointeddef
|
||||||
|
else
|
||||||
|
checkdef:=node.right.resultdef;
|
||||||
|
if checkdef.typ=objectdef then
|
||||||
|
current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(tobjectdef(checkdef).jvm_full_typename(true))))
|
||||||
|
else
|
||||||
|
current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(jvmencodetype(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);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{*****************************************************************************
|
||||||
|
TJVMAsNode
|
||||||
|
*****************************************************************************}
|
||||||
|
|
||||||
|
function tjvmasnode.target_specific_typecheck: boolean;
|
||||||
|
begin
|
||||||
|
result:=asis_target_specific_typecheck(self);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -509,6 +567,8 @@ implementation
|
|||||||
{ call-by-reference does not exist in Java, so it's no problem to
|
{ call-by-reference does not exist in Java, so it's no problem to
|
||||||
change a memory location to a register }
|
change a memory location to a register }
|
||||||
firstpass(left);
|
firstpass(left);
|
||||||
|
if right.nodetype<>typen then
|
||||||
|
firstpass(right);
|
||||||
expectloc:=LOC_REGISTER;
|
expectloc:=LOC_REGISTER;
|
||||||
result:=nil;
|
result:=nil;
|
||||||
end;
|
end;
|
||||||
@ -516,21 +576,34 @@ implementation
|
|||||||
|
|
||||||
procedure tjvmasnode.pass_generate_code;
|
procedure tjvmasnode.pass_generate_code;
|
||||||
begin
|
begin
|
||||||
secondpass(left);
|
asis_generate_code(self,a_checkcast);
|
||||||
thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,resultdef,left.location);
|
end;
|
||||||
location_freetemp(current_asmdata.CurrAsmList,left.location);
|
|
||||||
{ Perform a checkcast instruction, which will raise an exception in case
|
|
||||||
the actual type does not match/inherit from the expected type.
|
|
||||||
|
|
||||||
Object types need the full type name (package+class name), arrays only
|
|
||||||
the array definition }
|
{*****************************************************************************
|
||||||
if resultdef.typ=objectdef then
|
TJVMIsNode
|
||||||
current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_checkcast,current_asmdata.RefAsmSymbol(tobjectdef(resultdef).jvm_full_typename)))
|
*****************************************************************************}
|
||||||
else
|
|
||||||
current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_checkcast,current_asmdata.RefAsmSymbol(jvmencodetype(resultdef))));
|
|
||||||
location_reset(location,LOC_REGISTER,OS_ADDR);
|
function tjvmisnode.target_specific_typecheck: boolean;
|
||||||
location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,resultdef);
|
begin
|
||||||
thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
|
result:=asis_target_specific_typecheck(self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function tjvmisnode.pass_1: tnode;
|
||||||
|
begin
|
||||||
|
firstpass(left);
|
||||||
|
if right.nodetype<>typen then
|
||||||
|
firstpass(right);
|
||||||
|
expectloc:=LOC_REGISTER;
|
||||||
|
result:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure tjvmisnode.pass_generate_code;
|
||||||
|
begin
|
||||||
|
asis_generate_code(self,a_instanceof);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -539,4 +612,5 @@ implementation
|
|||||||
begin
|
begin
|
||||||
ctypeconvnode:=tjvmtypeconvnode;
|
ctypeconvnode:=tjvmtypeconvnode;
|
||||||
casnode:=tjvmasnode;
|
casnode:=tjvmasnode;
|
||||||
|
cisnode:=tjvmisnode;
|
||||||
end.
|
end.
|
||||||
|
@ -3364,7 +3364,8 @@ implementation
|
|||||||
{ relation checks are not possible }
|
{ relation checks are not possible }
|
||||||
end
|
end
|
||||||
{ or left must be a class }
|
{ or left must be a class }
|
||||||
else if is_class(left.resultdef) then
|
else if is_class(left.resultdef) or
|
||||||
|
is_javaclass(left.resultdef) then
|
||||||
begin
|
begin
|
||||||
{ the operands must be related }
|
{ the operands must be related }
|
||||||
if (not(tobjectdef(left.resultdef).is_related(
|
if (not(tobjectdef(left.resultdef).is_related(
|
||||||
|
@ -239,7 +239,8 @@ implementation
|
|||||||
firstpass(left)
|
firstpass(left)
|
||||||
end
|
end
|
||||||
else if not is_objcclass(left.resultdef) and
|
else if not is_objcclass(left.resultdef) and
|
||||||
not is_objcclassref(left.resultdef) then
|
not is_objcclassref(left.resultdef) and
|
||||||
|
not is_javaclass(left.resultdef) then
|
||||||
begin
|
begin
|
||||||
if not(nf_ignore_for_wpo in flags) and
|
if not(nf_ignore_for_wpo in flags) and
|
||||||
(not assigned(current_procinfo) or
|
(not assigned(current_procinfo) or
|
||||||
|
Loading…
Reference in New Issue
Block a user