Browse Source

* move conversions of winlinke widestring, variant and records/arrays-
with-init-info assignments into helper calls from
tassignmentnode.pass_typecheck to pass_1 so they can be optimised
in more cases (patch from Sergei Gorelkin)

git-svn-id: trunk@9410 -

Jonas Maebe 17 năm trước cách đây
mục cha
commit
d46b433778
1 tập tin đã thay đổi với 63 bổ sung59 xóa
  1. 63 59
      compiler/nld.pas

+ 63 - 59
compiler/nld.pas

@@ -582,64 +582,6 @@ implementation
                right:=nil;
                right:=nil;
                exit;
                exit;
              end;
              end;
-         end
-        { call helpers for variant, they can contain non ref. counted types like
-          vararrays which must be really copied }
-        else if left.resultdef.typ=variantdef then
-         begin
-           hp:=ccallparanode.create(ctypeconvnode.create_internal(
-                 caddrnode.create_internal(right),voidpointertype),
-               ccallparanode.create(ctypeconvnode.create_internal(
-                 caddrnode.create_internal(left),voidpointertype),
-               nil));
-           result:=ccallnode.createintern('fpc_variant_copy',hp);
-           left:=nil;
-           right:=nil;
-           exit;
-         end
-        { call helpers for composite types containing automated types }
-        else if (left.resultdef.needs_inittable) and
-            (left.resultdef.typ in [arraydef,objectdef,recorddef]) and
-            not is_dynamic_array(left.resultdef) then
-         begin
-           hp:=ccallparanode.create(caddrnode.create_internal(
-                  crttinode.create(tstoreddef(left.resultdef),initrtti,rdt_normal)),
-               ccallparanode.create(ctypeconvnode.create_internal(
-                 caddrnode.create_internal(left),voidpointertype),
-               ccallparanode.create(ctypeconvnode.create_internal(
-                 caddrnode.create_internal(right),voidpointertype),
-               nil)));
-           result:=ccallnode.createintern('fpc_copy_proc',hp);
-           left:=nil;
-           right:=nil;
-           exit;
-         end
-        { call helpers for windows widestrings, they aren't ref. counted }
-        else if (tf_winlikewidestring in target_info.flags) and is_widestring(left.resultdef) then
-         begin
-           { The first argument of fpc_widestr_assign is a var parameter. Properties cannot   }
-           { be passed to var or out parameters, because in that case setters/getters are not }
-           { used. Further, if we would allow it in case there are no getters or setters, you }
-           { would need source changes in case these are introduced later on, thus defeating  }
-           { part of the transparency advantages of properties. In this particular case,      }
-           { however:                                                                         }
-           {   a) if there is a setter, this code will not be used since then the assignment  }
-           {      will be converted to a procedure call                                       }
-           {   b) the getter is irrelevant, because fpc_widestr_assign must always decrease   }
-           {      the refcount of the field to which we are writing                           }
-           {   c) source code changes are not required if a setter is added/removed, because  }
-           {      this transformation is handled at compile time                              }
-           {  -> we can remove the nf_isproperty flag (if any) from left, so that in case it  }
-           {     is a property which refers to a field without a setter call, we will not get }
-           {     an error about trying to pass a property as a var parameter                  }
-           exclude(left.flags,nf_isproperty);
-           hp:=ccallparanode.create(ctypeconvnode.create_internal(right,voidpointertype),
-               ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),
-               nil));
-           result:=ccallnode.createintern('fpc_widestr_assign',hp);
-           left:=nil;
-           right:=nil;
-           exit;
          end;
          end;
 
 
         { check if local proc/func is assigned to procvar }
         { check if local proc/func is assigned to procvar }
@@ -699,7 +641,69 @@ implementation
                  exit;
                  exit;
                end;
                end;
             end;
             end;
-           end;
+           end
+        { call helpers for composite types containing automated types }
+        else if (left.resultdef.needs_inittable) and
+            (left.resultdef.typ in [arraydef,objectdef,recorddef]) and
+            not is_interfacecom(left.resultdef) and
+            not is_dynamic_array(left.resultdef) then
+         begin
+           hp:=ccallparanode.create(caddrnode.create_internal(
+                  crttinode.create(tstoreddef(left.resultdef),initrtti,rdt_normal)),
+               ccallparanode.create(ctypeconvnode.create_internal(
+                 caddrnode.create_internal(left),voidpointertype),
+               ccallparanode.create(ctypeconvnode.create_internal(
+                 caddrnode.create_internal(right),voidpointertype),
+               nil)));
+           result:=ccallnode.createintern('fpc_copy_proc',hp);
+           firstpass(result);
+           left:=nil;
+           right:=nil;
+           exit;
+         end
+        { call helpers for variant, they can contain non ref. counted types like
+          vararrays which must be really copied }
+        else if left.resultdef.typ=variantdef then
+         begin
+           hp:=ccallparanode.create(ctypeconvnode.create_internal(
+                 caddrnode.create_internal(right),voidpointertype),
+               ccallparanode.create(ctypeconvnode.create_internal(
+                 caddrnode.create_internal(left),voidpointertype),
+               nil));
+           result:=ccallnode.createintern('fpc_variant_copy',hp);
+           firstpass(result);
+           left:=nil;
+           right:=nil;
+           exit;
+         end
+        { call helpers for windows widestrings, they aren't ref. counted }
+        else if (tf_winlikewidestring in target_info.flags) and is_widestring(left.resultdef) then
+         begin
+           { The first argument of fpc_widestr_assign is a var parameter. Properties cannot   }
+           { be passed to var or out parameters, because in that case setters/getters are not }
+           { used. Further, if we would allow it in case there are no getters or setters, you }
+           { would need source changes in case these are introduced later on, thus defeating  }
+           { part of the transparency advantages of properties. In this particular case,      }
+           { however:                                                                         }
+           {   a) if there is a setter, this code will not be used since then the assignment  }
+           {      will be converted to a procedure call                                       }
+           {   b) the getter is irrelevant, because fpc_widestr_assign must always decrease   }
+           {      the refcount of the field to which we are writing                           }
+           {   c) source code changes are not required if a setter is added/removed, because  }
+           {      this transformation is handled at compile time                              }
+           {  -> we can remove the nf_isproperty flag (if any) from left, so that in case it  }
+           {     is a property which refers to a field without a setter call, we will not get }
+           {     an error about trying to pass a property as a var parameter                  }
+           exclude(left.flags,nf_isproperty);
+           hp:=ccallparanode.create(ctypeconvnode.create_internal(right,voidpointertype),
+               ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),
+               nil));
+           result:=ccallnode.createintern('fpc_widestr_assign',hp);
+           firstpass(result);
+           left:=nil;
+           right:=nil;
+           exit;
+         end;
       end;
       end;