Răsfoiți Sursa

* 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 -

Jonas Maebe 9 ani în urmă
părinte
comite
8917633199
3 a modificat fișierele cu 37 adăugiri și 71 ștergeri
  1. 6 0
      compiler/jvm/njvminl.pas
  2. 2 67
      compiler/ncginl.pas
  3. 29 4
      compiler/ninl.pas

+ 6 - 0
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;

+ 2 - 67
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;
 
 

+ 29 - 4
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: