From 8917633199c1ad32893833104129441eeba5ccee Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Sun, 27 Dec 2015 14:22:06 +0000 Subject: [PATCH] * 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 - --- compiler/jvm/njvminl.pas | 6 ++++ compiler/ncginl.pas | 69 ++-------------------------------------- compiler/ninl.pas | 33 ++++++++++++++++--- 3 files changed, 37 insertions(+), 71 deletions(-) diff --git a/compiler/jvm/njvminl.pas b/compiler/jvm/njvminl.pas index 8c11487459..fe25b67d82 100644 --- a/compiler/jvm/njvminl.pas +++ b/compiler/jvm/njvminl.pas @@ -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; diff --git a/compiler/ncginl.pas b/compiler/ncginl.pas index c1542561d7..0ae978d180 100644 --- a/compiler/ncginl.pas +++ b/compiler/ncginl.pas @@ -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; diff --git a/compiler/ninl.pas b/compiler/ninl.pas index e652d5a357..696097924e 100644 --- a/compiler/ninl.pas +++ b/compiler/ninl.pas @@ -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: