瀏覽代碼

* only add the llvm "sret" attribute to "struct return" parameters if they
are the first parameter (as required by llvm)
o ensure that for AArch64, "struct return" the parameter always is the first
parameter, as it needs to be returned in a special register there

git-svn-id: trunk@31676 -

Jonas Maebe 10 年之前
父節點
當前提交
bf10ae45de
共有 2 個文件被更改,包括 25 次插入1 次删除
  1. 15 1
      compiler/llvm/llvmdef.pas
  2. 10 0
      compiler/symconst.pas

+ 15 - 1
compiler/llvm/llvmdef.pas

@@ -610,8 +610,22 @@ implementation
           { sret: hidden pointer for structured function result }
           if vo_is_funcret in hp.varoptions then
             begin
+              { "sret" is only valid for the firstparameter, while in FPC this
+                can sometimes be second one (self comes before). In general,
+                this is not a problem: we can just leave out sret, which means
+                the result will be a bit less well optimised), but it is for
+                AArch64: there, the sret parameter must be passed in a different
+                register (-> paranr_result is smaller than paranr_self for that
+                platform in symconst) }
+{$ifdef aarch64}
+              if not first then
+                internalerror(2015101404);
+{$endif aarch64}
               if withattributes then
-                encodedstr:=encodedstr+' sret'
+                 if first then
+                   encodedstr:=encodedstr+' sret'
+                 else { we can add some other attributes to optimise things,}
+                   encodedstr:=encodedstr+' noalias nocapture';
             end
           else if not paramanager.push_addr_param(hp.varspez,hp.vardef,proccalloption) and
              llvmbyvalparaloc(paraloc) then

+ 10 - 0
compiler/symconst.pas

@@ -116,8 +116,18 @@ const
   paranr_blockselfpara = 1;
   paranr_parentfp = 2;
   paranr_parentfp_delphi_cc_leftright = 2;
+{$ifndef aarch64}
   paranr_self = 3;
   paranr_result = 4;
+{$else aarch64}
+  { on AArch64, the result parameter is passed in a special register, so its
+    order doesn't really matter -- except for LLVM, where the "sret" parameter
+    must always be the first -> give it a higher number; can't do it for other
+    platforms, because that would change the register assignment/parameter order
+    and the current one is presumably Delphi-compatible }
+  paranr_result = 3;
+  paranr_self = 4;
+{$endif aarch64}
   paranr_vmt = 5;
 
   { the implicit parameters for Objective-C methods need to come