Browse Source

* Nil constants that are type converted to a method procvar are now
properly converted. The conversion is done at runtime to generate
a two pointer memory reference as result location, something
which the code generator can handle very well, which minimizes
the chance of side effects.

git-svn-id: trunk@7978 -

daniel 18 years ago
parent
commit
6e0a7bb0eb
3 changed files with 44 additions and 1 deletions
  1. 7 1
      compiler/defcmp.pas
  2. 13 0
      compiler/ncgcnv.pas
  3. 24 0
      compiler/ncnv.pas

+ 7 - 1
compiler/defcmp.pas

@@ -63,6 +63,7 @@ interface
           tc_int_2_real,
           tc_int_2_real,
           tc_real_2_currency,
           tc_real_2_currency,
           tc_proc_2_procvar,
           tc_proc_2_procvar,
+          tc_nil_2_methodprocvar,
           tc_arrayconstructor_2_set,
           tc_arrayconstructor_2_set,
           tc_set_to_set,
           tc_set_to_set,
           tc_cord_2_pointer,
           tc_cord_2_pointer,
@@ -1155,7 +1156,12 @@ implementation
                      { nil is compatible with procvars }
                      { nil is compatible with procvars }
                      if (fromtreetype=niln) then
                      if (fromtreetype=niln) then
                       begin
                       begin
-                        doconv:=tc_equal;
+                        if not Tprocvardef(def_to).is_addressonly then
+                          {Nil to method pointers requires to convert a single
+                           pointer nil value to a two pointer procvardef.}
+                          doconv:=tc_nil_2_methodprocvar
+                        else
+                          doconv:=tc_equal;
                         eq:=te_convert_l1;
                         eq:=te_convert_l1;
                       end
                       end
                      else
                      else

+ 13 - 0
compiler/ncgcnv.pas

@@ -41,6 +41,7 @@ interface
          procedure second_real_to_real;override;
          procedure second_real_to_real;override;
          procedure second_cord_to_pointer;override;
          procedure second_cord_to_pointer;override;
          procedure second_proc_to_procvar;override;
          procedure second_proc_to_procvar;override;
+         procedure second_nil_to_methodprocvar;override;
          procedure second_bool_to_int;override;
          procedure second_bool_to_int;override;
          procedure second_bool_to_bool;override;
          procedure second_bool_to_bool;override;
          procedure second_ansistring_to_pchar;override;
          procedure second_ansistring_to_pchar;override;
@@ -372,6 +373,18 @@ interface
           location_copy(location,left.location);
           location_copy(location,left.location);
       end;
       end;
 
 
+    procedure Tcgtypeconvnode.second_nil_to_methodprocvar;
+    
+    var r:Treference;
+
+    begin
+      tg.gettemp(current_asmdata.currasmlist,2*sizeof(aword),tt_normal,r);
+      location_reset(location,LOC_REFERENCE,OS_NO);
+      location.reference:=r;
+      cg.a_load_const_ref(current_asmdata.currasmlist,OS_ADDR,0,r);
+      inc(r.offset,8);
+      cg.a_load_const_ref(current_asmdata.currasmlist,OS_ADDR,0,r);
+    end;
 
 
     procedure tcgtypeconvnode.second_bool_to_int;
     procedure tcgtypeconvnode.second_bool_to_int;
       var
       var

+ 24 - 0
compiler/ncnv.pas

@@ -100,6 +100,7 @@ interface
           function first_int_to_bool : tnode;virtual;
           function first_int_to_bool : tnode;virtual;
           function first_bool_to_bool : tnode;virtual;
           function first_bool_to_bool : tnode;virtual;
           function first_proc_to_procvar : tnode;virtual;
           function first_proc_to_procvar : tnode;virtual;
+          function first_nil_to_methodprocvar : tnode;virtual;
           function first_set_to_set : tnode;virtual;
           function first_set_to_set : tnode;virtual;
           function first_cord_to_pointer : tnode;virtual;
           function first_cord_to_pointer : tnode;virtual;
           function first_ansistring_to_pchar : tnode;virtual;
           function first_ansistring_to_pchar : tnode;virtual;
@@ -126,6 +127,7 @@ interface
           function _first_int_to_bool : tnode;
           function _first_int_to_bool : tnode;
           function _first_bool_to_bool : tnode;
           function _first_bool_to_bool : tnode;
           function _first_proc_to_procvar : tnode;
           function _first_proc_to_procvar : tnode;
+          function _first_nil_to_methodprocvar : tnode;
           function _first_cord_to_pointer : tnode;
           function _first_cord_to_pointer : tnode;
           function _first_ansistring_to_pchar : tnode;
           function _first_ansistring_to_pchar : tnode;
           function _first_arrayconstructor_to_set : tnode;
           function _first_arrayconstructor_to_set : tnode;
@@ -146,6 +148,7 @@ interface
           procedure _second_real_to_real;virtual;
           procedure _second_real_to_real;virtual;
           procedure _second_cord_to_pointer;virtual;
           procedure _second_cord_to_pointer;virtual;
           procedure _second_proc_to_procvar;virtual;
           procedure _second_proc_to_procvar;virtual;
+          procedure _second_nil_to_methodprocvar;virtual;
           procedure _second_bool_to_int;virtual;
           procedure _second_bool_to_int;virtual;
           procedure _second_int_to_bool;virtual;
           procedure _second_int_to_bool;virtual;
           procedure _second_bool_to_bool;virtual;
           procedure _second_bool_to_bool;virtual;
@@ -168,6 +171,7 @@ interface
           procedure second_real_to_real;virtual;abstract;
           procedure second_real_to_real;virtual;abstract;
           procedure second_cord_to_pointer;virtual;abstract;
           procedure second_cord_to_pointer;virtual;abstract;
           procedure second_proc_to_procvar;virtual;abstract;
           procedure second_proc_to_procvar;virtual;abstract;
+          procedure second_nil_to_methodprocvar;virtual;abstract;
           procedure second_bool_to_int;virtual;abstract;
           procedure second_bool_to_int;virtual;abstract;
           procedure second_int_to_bool;virtual;abstract;
           procedure second_int_to_bool;virtual;abstract;
           procedure second_bool_to_bool;virtual;abstract;
           procedure second_bool_to_bool;virtual;abstract;
@@ -726,6 +730,7 @@ implementation
           'tc_int_2_real',
           'tc_int_2_real',
           'tc_real_2_currency',
           'tc_real_2_currency',
           'tc_proc_2_procvar',
           'tc_proc_2_procvar',
+          'tc_nil_2_methodprocvar',
           'tc_arrayconstructor_2_set',
           'tc_arrayconstructor_2_set',
           'tc_set_2_set',
           'tc_set_2_set',
           'tc_cord_2_pointer',
           'tc_cord_2_pointer',
@@ -1461,6 +1466,7 @@ implementation
           { int_2_real } @ttypeconvnode.typecheck_int_to_real,
           { int_2_real } @ttypeconvnode.typecheck_int_to_real,
           { real_2_currency } @ttypeconvnode.typecheck_real_to_currency,
           { real_2_currency } @ttypeconvnode.typecheck_real_to_currency,
           { proc_2_procvar } @ttypeconvnode.typecheck_proc_to_procvar,
           { proc_2_procvar } @ttypeconvnode.typecheck_proc_to_procvar,
+          { nil_2_methodprocvar } nil,
           { arrayconstructor_2_set } @ttypeconvnode.typecheck_arrayconstructor_to_set,
           { arrayconstructor_2_set } @ttypeconvnode.typecheck_arrayconstructor_to_set,
           { set_to_set } @ttypeconvnode.typecheck_set_to_set,
           { set_to_set } @ttypeconvnode.typecheck_set_to_set,
           { cord_2_pointer } @ttypeconvnode.typecheck_cord_to_pointer,
           { cord_2_pointer } @ttypeconvnode.typecheck_cord_to_pointer,
@@ -2272,6 +2278,13 @@ implementation
           end
           end
       end;
       end;
 
 
+    function ttypeconvnode.first_nil_to_methodprocvar : tnode;
+
+    begin
+      first_nil_to_methodprocvar:=nil;
+      registersint:=0;
+      expectloc:=LOC_REFERENCE;
+    end;
 
 
     function ttypeconvnode.first_set_to_set : tnode;
     function ttypeconvnode.first_set_to_set : tnode;
       var
       var
@@ -2422,6 +2435,11 @@ implementation
          result:=first_proc_to_procvar;
          result:=first_proc_to_procvar;
       end;
       end;
 
 
+    function ttypeconvnode._first_nil_to_methodprocvar : tnode;
+      begin
+         result:=first_nil_to_methodprocvar;
+      end;
+
     function ttypeconvnode._first_set_to_set : tnode;
     function ttypeconvnode._first_set_to_set : tnode;
       begin
       begin
          result:=first_set_to_set;
          result:=first_set_to_set;
@@ -2479,6 +2497,7 @@ implementation
            @ttypeconvnode._first_int_to_real,
            @ttypeconvnode._first_int_to_real,
            nil, { removed in typecheck_real_to_currency }
            nil, { removed in typecheck_real_to_currency }
            @ttypeconvnode._first_proc_to_procvar,
            @ttypeconvnode._first_proc_to_procvar,
+           @ttypeconvnode._first_nil_to_methodprocvar,
            @ttypeconvnode._first_arrayconstructor_to_set,
            @ttypeconvnode._first_arrayconstructor_to_set,
            @ttypeconvnode._first_set_to_set,
            @ttypeconvnode._first_set_to_set,
            @ttypeconvnode._first_cord_to_pointer,
            @ttypeconvnode._first_cord_to_pointer,
@@ -2646,6 +2665,10 @@ implementation
         second_proc_to_procvar;
         second_proc_to_procvar;
       end;
       end;
 
 
+    procedure ttypeconvnode._second_nil_to_methodprocvar;
+      begin
+        second_nil_to_methodprocvar;
+      end;
 
 
     procedure ttypeconvnode._second_bool_to_int;
     procedure ttypeconvnode._second_bool_to_int;
       begin
       begin
@@ -2721,6 +2744,7 @@ implementation
            @ttypeconvnode._second_int_to_real,
            @ttypeconvnode._second_int_to_real,
            @ttypeconvnode._second_nothing, { real_to_currency, handled in resultdef pass }
            @ttypeconvnode._second_nothing, { real_to_currency, handled in resultdef pass }
            @ttypeconvnode._second_proc_to_procvar,
            @ttypeconvnode._second_proc_to_procvar,
+           @ttypeconvnode._second_nil_to_methodprocvar,
            @ttypeconvnode._second_nothing, { arrayconstructor_to_set }
            @ttypeconvnode._second_nothing, { arrayconstructor_to_set }
            @ttypeconvnode._second_nothing, { second_set_to_set, handled in first pass }
            @ttypeconvnode._second_nothing, { second_set_to_set, handled in first pass }
            @ttypeconvnode._second_cord_to_pointer,
            @ttypeconvnode._second_cord_to_pointer,