diff --git a/compiler/i386/cpupara.pas b/compiler/i386/cpupara.pas
index d310fb5279..f33c2ffc27 100644
--- a/compiler/i386/cpupara.pas
+++ b/compiler/i386/cpupara.pas
@@ -292,7 +292,7 @@ unit cpupara;
       var
         retcgsize  : tcgsize;
         paraloc : pcgparalocation;
-        sym: tfieldvarsym;
+        fdef,
         usedef: tdef;
         handled: boolean;
       begin
@@ -307,10 +307,10 @@ unit cpupara;
                                    system_i386_os2,system_i386_emx]) and
            ((usedef.typ=recorddef) or
             is_object(usedef)) and
-           tabstractrecordsymtable(tabstractrecorddef(usedef).symtable).has_single_field(sym) and
-           (sym.vardef.typ=floatdef) and
-           (tfloatdef(sym.vardef).floattype in [s32real,s64real]) then
-          usedef:=sym.vardef;
+           tabstractrecordsymtable(tabstractrecorddef(usedef).symtable).has_single_field(fdef) and
+           (fdef.typ=floatdef) and
+           (tfloatdef(fdef).floattype in [s32real,s64real]) then
+          usedef:=fdef;
 
         handled:=set_common_funcretloc_info(p,usedef,retcgsize,result);
         { normally forcetempdef is passed straight through to
diff --git a/compiler/powerpc/cpupara.pas b/compiler/powerpc/cpupara.pas
index 8855333573..b260af97e9 100644
--- a/compiler/powerpc/cpupara.pas
+++ b/compiler/powerpc/cpupara.pas
@@ -330,13 +330,13 @@ unit cpupara;
          paralen: aint;
          nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
          locdef,
+         fdef,
          paradef : tdef;
          paraloc : pcgparalocation;
          i  : integer;
          hp : tparavarsym;
          loc : tcgloc;
          paracgsize: tcgsize;
-         sym: tfieldvarsym;
          firstparaloc: boolean;
 
       begin
@@ -404,13 +404,12 @@ unit cpupara;
                       { if a record has only one field and that field is }
                       { non-composite (not array or record), it must be  }
                       { passed according to the rules of that type.      }
-                      sym:=nil;
-                      if tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(sym) and
-                         ((sym.vardef.typ=floatdef) or
+                      if tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(fdef) and
+                         ((fdef.typ=floatdef) or
                           ((target_info.system=system_powerpc_darwin) and
-                           (sym.vardef.typ in [orddef,enumdef]))) then
+                           (fdef.typ in [orddef,enumdef]))) then
                         begin
-                          paradef:=sym.vardef;
+                          paradef:=fdef;
                           paracgsize:=def_cgsize(paradef);
                         end
                       else
diff --git a/compiler/powerpc64/cpupara.pas b/compiler/powerpc64/cpupara.pas
index 65f06490cd..51f8c4e378 100644
--- a/compiler/powerpc64/cpupara.pas
+++ b/compiler/powerpc64/cpupara.pas
@@ -320,7 +320,6 @@ var
   locdef,
   tmpdef: tdef;
   paralen: aint;
-  fsym: tfieldvarsym;
   parashift: byte;
   tailpadding,
   firstparaloc,
@@ -422,10 +421,10 @@ implemented
     { AIX/ELFv1 b) }
     else if (target_info.abi in [abi_powerpc_aix,abi_powerpc_sysv]) and
        (paradef.typ=recorddef) and
-       tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(fsym) and
-       (fsym.vardef.typ=floatdef) then
+       tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(tmpdef) and
+       (tmpdef.typ=floatdef) then
       begin
-        paradef:=fsym.vardef;
+        paradef:=tmpdef;
         loc:=getparaloc(paradef);
         paracgsize:=def_cgsize(paradef)
       end
diff --git a/compiler/symtable.pas b/compiler/symtable.pas
index 89aeed0668..b8204bb508 100644
--- a/compiler/symtable.pas
+++ b/compiler/symtable.pas
@@ -86,7 +86,7 @@ interface
           procedure addalignmentpadding;
           procedure insertdef(def:TDefEntry);override;
           function is_packed: boolean;
-          function has_single_field(out sym:tfieldvarsym): boolean;
+          function has_single_field(out def:tdef): boolean;
           function get_unit_symtable: tsymtable;
         protected
           { size in bytes including padding }
@@ -1238,9 +1238,12 @@ implementation
       end;
 
 
-    function tabstractrecordsymtable.has_single_field(out sym: tfieldvarsym): boolean;
+    function tabstractrecordsymtable.has_single_field(out def:tdef): boolean;
       var
         i: longint;
+        currentsymlist: TFPHashObjectList;
+        currentdef: tdef;
+        sym: tfieldvarsym;
       begin
         result:=false;
         { If a record contains a union, it does not contain a "single
@@ -1250,19 +1253,51 @@ implementation
            trecorddef(defowner).isunion then
           exit;
         { a record/object can contain other things than fields }
-        for i:=0 to SymList.Count-1 do
-          begin
-            if tsym(symlist[i]).typ=fieldvarsym then
-              begin
-                if result then
-                  begin
-                    result:=false;
-                    exit;
-                  end;
-                result:=true;
-                sym:=tfieldvarsym(symlist[i])
-              end;
-          end;
+        currentsymlist:=symlist;
+        { recurse in arrays and records }
+        sym:=nil;
+        repeat
+          { record has one field? }
+          for i:=0 to currentsymlist.Count-1 do
+            begin
+              if tsym(symlist[i]).typ=fieldvarsym then
+                begin
+                  if result then
+                    begin
+                      result:=false;
+                      exit;
+                    end;
+                  result:=true;
+                  sym:=tfieldvarsym(symlist[i])
+                end;
+            end;
+          if assigned(sym) then
+            begin
+              { if the field is an array, does it contain one element? }
+              currentdef:=sym.vardef;
+              while (currentdef.typ=arraydef) and
+                    not is_special_array(currentdef) do
+                begin
+                  if tarraydef(currentdef).elecount<>1 then
+                    begin
+                      result:=false;
+                      exit;
+                    end;
+                  currentdef:=tarraydef(currentdef).elementdef;
+                end;
+              { if the array element is again a record, continue descending }
+              if currentdef.typ=recorddef then
+                currentsymlist:=trecorddef(currentdef).symtable.SymList
+              else
+                begin
+                  { otherwise we found the type of the single element }
+                  def:=currentdef;
+                  exit;
+                end;
+            end
+          else
+            exit
+        until false;
       end;
 
     function tabstractrecordsymtable.get_unit_symtable: tsymtable;
diff --git a/compiler/x86_64/cpupara.pas b/compiler/x86_64/cpupara.pas
index c61712b10b..7c72164511 100644
--- a/compiler/x86_64/cpupara.pas
+++ b/compiler/x86_64/cpupara.pas
@@ -1069,6 +1069,7 @@ unit cpupara;
                                                             var intparareg,mmparareg,parasize:longint;varargsparas: boolean);
       var
         hp         : tparavarsym;
+        fdef,
         paradef    : tdef;
         paraloc    : pcgparalocation;
         subreg     : tsubregister;
@@ -1082,7 +1083,6 @@ unit cpupara;
         i,
         varalign,
         paraalign  : longint;
-        sym: tfieldvarsym;
       begin
         paraalign:=get_para_align(p.proccalloption);
         { Register parameters are assigned from left to right }
@@ -1095,10 +1095,10 @@ unit cpupara;
             if (target_info.system=system_x86_64_win64) and
                ((paradef.typ=recorddef) {or
                is_object(paradef)}) and
-               tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(sym) and
-               (sym.vardef.typ=floatdef) and
-               (tfloatdef(sym.vardef).floattype in [s32real,s64real]) then
-              paradef:=sym.vardef;
+               tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(fdef) and
+               (fdef.typ=floatdef) and
+               (tfloatdef(fdef).floattype in [s32real,s64real]) then
+              paradef:=fdef;
 
             pushaddr:=push_addr_param(hp.varspez,paradef,p.proccalloption);
             if pushaddr then