Переглянути джерело

* set the correct resultdef after converting a dynamic array to an open array
in ncnv
* handle the fact that we overwrite the open array resultdef of a parameters'
left node with the original resultdef (i.e., also for dynamic arrays) with
regards to LLVM type rules
o use the parameter's formal type (open array) instead of the value's type
(dynamic array) when loading/using its value, since that's the type the
value has been converted to
o this change is not really nice since it adds several independent checks in
different places, but I can't find a way to nicely unify the code to work
around this (nor one to get rid of that hack in the first place)

git-svn-id: trunk@34515 -

Jonas Maebe 9 роки тому
батько
коміт
66be068365
3 змінених файлів з 26 додано та 3 видалено
  1. 12 0
      compiler/ncal.pas
  2. 13 1
      compiler/ncgcal.pas
  3. 1 2
      compiler/ncnv.pas

+ 12 - 0
compiler/ncal.pas

@@ -666,6 +666,18 @@ implementation
             is_managed_type(tarraydef(resultdef).elementdef)) and
             is_managed_type(tarraydef(resultdef).elementdef)) and
            not(target_info.system in systems_garbage_collected_managed_types) then
            not(target_info.system in systems_garbage_collected_managed_types) then
           begin
           begin
+            { after converting a parameter to an open array, its resultdef is
+              set back to its original resultdef so we can get the value of the
+              "high" parameter correctly, even though we already inserted a
+              type conversion to "open array". Since here we work on this
+              converted parameter, set it back to the type to which it was
+              converted in order to avoid type mismatches at the LLVM level }
+            if is_open_array(parasym.vardef) and
+               is_dynamic_array(orgparadef) then
+              begin
+                left.resultdef:=resultdef;
+                orgparadef:=resultdef;
+              end;
             paraaddrtype:=cpointerdef.getreusable(orgparadef);
             paraaddrtype:=cpointerdef.getreusable(orgparadef);
             { create temp with address of the parameter }
             { create temp with address of the parameter }
             temp:=ctempcreatenode.create(
             temp:=ctempcreatenode.create(

+ 13 - 1
compiler/ncgcal.pas

@@ -163,10 +163,22 @@ implementation
 
 
 
 
     procedure tcgcallparanode.push_addr_para;
     procedure tcgcallparanode.push_addr_para;
+      var
+        valuedef: tdef;
       begin
       begin
         if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
         if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
           internalerror(200304235);
           internalerror(200304235);
-        hlcg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,left.resultdef,left.location.reference,tempcgpara);
+        { see the call to keep_para_array_range in ncal: if that call returned
+          true, we overwrite the resultdef of left with its original resultdef
+          (to keep track of the range of the original array); we inserted a type
+          conversion to parasym.vardef, so that is the type this value actually
+          has }
+        if is_dynamic_array(left.resultdef) and
+           is_open_array(parasym.vardef) then
+          valuedef:=parasym.vardef
+        else
+          valuedef:=left.resultdef;
+        hlcg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,valuedef,left.location.reference,tempcgpara);
       end;
       end;
 
 
 
 

+ 1 - 2
compiler/ncnv.pas

@@ -1611,13 +1611,12 @@ implementation
       begin
       begin
         { a dynamic array is a pointer to an array, so to convert it to }
         { a dynamic array is a pointer to an array, so to convert it to }
         { an open array, we have to dereference it (JM)                 }
         { an open array, we have to dereference it (JM)                 }
-        result := ctypeconvnode.create_internal(left,voidpointertype);
+        result := ctypeconvnode.create_internal(left,cpointerdef.getreusable(resultdef));
         typecheckpass(result);
         typecheckpass(result);
         { left is reused }
         { left is reused }
         left := nil;
         left := nil;
         result := cderefnode.create(result);
         result := cderefnode.create(result);
         include(result.flags,nf_no_checkpointer);
         include(result.flags,nf_no_checkpointer);
-        result.resultdef := resultdef;
       end;
       end;