* implement sizeof/typeof completely at the node level, based on

loadvmtaddr and vmt_def
   o give an error when trying to use sizeof on a class/object when
     targeting the JVM (can't get/load the data size there)

git-svn-id: trunk@32764 -
This commit is contained in:
Jonas Maebe 2015-12-27 14:22:06 +00:00
parent 59eff35c5d
commit 8917633199
3 changed files with 37 additions and 71 deletions

View File

@ -305,6 +305,12 @@ implementation
begin
result:=typecheck_new(handled);
end;
in_sizeof_x:
begin
{ can't get the size of the data of a class/object }
if left.resultdef.typ in [objectdef,classrefdef] then
Message(parser_e_illegal_expression);
end;
end;
if not handled then
result:=inherited pass_typecheck;

View File

@ -208,74 +208,9 @@ implementation
{ second_handle_ the sizeof and typeof routines }
procedure tcginlinenode.second_SizeOfTypeOf;
var
href,
hrefvmt : treference;
hregister : tregister;
begin
location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
{ for both cases load vmt }
if left.nodetype=typen then
begin
hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,voidpointertype);
reference_reset_symbol(href,current_asmdata.RefAsmSymbol(tobjectdef(left.resultdef).vmt_mangledname,AT_DATA),0,voidpointertype.size);
hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,voidpointertype,voidpointertype,href,hregister);
end
else
begin
secondpass(left);
hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,voidpointertype);
{ handle self inside a method of a class }
case left.location.loc of
LOC_CREGISTER,
LOC_REGISTER :
begin
if (left.resultdef.typ=classrefdef) or
(po_staticmethod in current_procinfo.procdef.procoptions) then
hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,voidpointertype,voidpointertype,left.location.register,hregister)
else
begin
{ load VMT pointer }
hlcg.reference_reset_base(hrefvmt,voidpointertype,left.location.register,tobjectdef(left.resultdef).vmt_offset,voidpointertype.size);
hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,voidpointertype,voidpointertype,hrefvmt,hregister);
end
end;
LOC_REFERENCE,
LOC_CREFERENCE :
begin
if is_class(left.resultdef) then
begin
{ deref class }
hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,voidpointertype,voidpointertype,left.location.reference,hregister);
hlcg.g_maybe_testself(current_asmdata.CurrAsmList,left.resultdef,hregister);
{ load VMT pointer }
hlcg.reference_reset_base(hrefvmt,voidpointertype,hregister,tobjectdef(left.resultdef).vmt_offset,voidpointertype.size);
hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,voidpointertype,voidpointertype,hrefvmt,hregister);
end
else
begin
{ load VMT pointer, but not for classrefdefs }
if (left.resultdef.typ=objectdef) then
begin
inc(left.location.reference.offset,tobjectdef(left.resultdef).vmt_offset);
left.location.reference.alignment:=newalignment(left.location.reference.alignment,tobjectdef(left.resultdef).vmt_offset);
end;
hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,voidpointertype,voidpointertype,left.location.reference,hregister);
end;
end;
else
internalerror(200301301);
end;
end;
{ in sizeof load size }
if inlinenumber=in_sizeof_x then
begin
hlcg.reference_reset_base(href,voidpointertype,hregister,0,voidpointertype.size);
hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,href,hregister);
end;
location.register:=hregister;
{ handled in pass 1 }
internalerror(2015122701);
end;

View File

@ -3296,6 +3296,7 @@ implementation
var
hp: tnode;
shiftconst: longint;
objdef: tobjectdef;
begin
result:=nil;
@ -3341,10 +3342,34 @@ implementation
in_typeof_x:
begin
expectloc:=LOC_REGISTER;
if (left.nodetype=typen) and
(cs_create_pic in current_settings.moduleswitches) and
(tf_pic_uses_got in target_info.flags) then
include(current_procinfo.flags,pi_needs_got);
case left.resultdef.typ of
objectdef,classrefdef:
begin
if left.resultdef.typ=objectdef then
begin
result:=cloadvmtaddrnode.create(left);
objdef:=tobjectdef(left.resultdef);
end
else
begin
result:=left;
objdef:=tobjectdef(tclassrefdef(left.resultdef).pointeddef);
end;
left:=nil;
if inlinenumber=in_sizeof_x then
begin
inserttypeconv_explicit(result,cpointerdef.getreusable(objdef.vmt_def));
result:=cderefnode.create(result);
result:=genloadfield(result,'VINSTANCESIZE');
end
else
inserttypeconv_explicit(result,voidpointertype);
end;
undefineddef:
;
else
internalerror(2015122702);
end;
end;
in_length_x: