[PATCH] pr13012: Support -fpcc-struct-return for x86-32

Arthur O'Dwyer arthur.j.odwyer at gmail.com
Fri Jun 7 12:07:19 PDT 2013


On Wed, Jun 5, 2013 at 1:23 PM, Arthur O'Dwyer
<arthur.j.odwyer at gmail.com> wrote:
>
>   This is my first post to cfe-commits, so my apologies if I get
> something wrong.
> A while back I filed an issue on Bugzilla requesting support for
> -fpcc-struct-return:
> http://llvm.org/bugs/show_bug.cgi?id=13012
>
> Recently I wrote a real patch [...] I believe I don't have the necessary
> credentials to commit the patch anyway, so basically I'm looking for
> a patron to adopt this patch. :)
>
> To observe what the patch does:
>   echo "struct S {int i;} foo() {return (struct S){42};}" >foo.c
>   clang -m32 -O3 -fomit-frame-pointer foo.c -S -o reg.s
>   clang -m32 -O3 -fomit-frame-pointer foo.c -S -o pcc.s -fpcc-struct-return
>   diff reg.s pcc.s

Ping? Any takers? Any comments at all?

-Arthur


Index: include/clang/Frontend/CodeGenOptions.def
===================================================================
--- include/clang/Frontend/CodeGenOptions.def (revision 183239)
+++ include/clang/Frontend/CodeGenOptions.def (working copy)
@@ -85,6 +85,7 @@
                                         ///< enabled.
 VALUE_CODEGENOPT(OptimizationLevel, 3, 0) ///< The -O[0-4] option specified.
 VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2)
is specified.
+VALUE_CODEGENOPT(PassSmallStructsConvention, 2, 0) /// If
-fpcc-struct-return (==1) or -freg-struct-return (==2) is specified.
 CODEGENOPT(RelaxAll          , 1, 0) ///< Relax all machine code instructions.
 CODEGENOPT(RelaxedAliasing   , 1, 0) ///< Set when
-fno-strict-aliasing is enabled.
 CODEGENOPT(StructPathTBAA    , 1, 0) ///< Whether or not to use
struct-path TBAA.
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td (revision 183239)
+++ include/clang/Driver/Options.td (working copy)
@@ -659,6 +659,8 @@
   HelpText<"Specify the default maximum struct packing alignment">;
 def fpascal_strings : Flag<["-"], "fpascal-strings">, Group<f_Group>,
Flags<[CC1Option]>,
   HelpText<"Recognize and construct Pascal-style string literals">;
+def fpcc_struct_return : Flag<["-"], "fpcc-struct-return">,
Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"Return small structs on the stack">;
 def fpch_preprocess : Flag<["-"], "fpch-preprocess">, Group<f_Group>;
 def fpic : Flag<["-"], "fpic">, Group<f_Group>;
 def fno_pic : Flag<["-"], "fno-pic">, Group<f_Group>;
@@ -668,6 +670,8 @@
 def fprofile_generate : Flag<["-"], "fprofile-generate">, Group<f_Group>;
 def framework : Separate<["-"], "framework">, Flags<[LinkerInput]>;
 def frandom_seed_EQ : Joined<["-"], "frandom-seed=">,
Group<clang_ignored_f_Group>;
+def freg_struct_return : Flag<["-"], "freg-struct-return">,
Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"Return small structs in registers">;
 def frtti : Flag<["-"], "frtti">, Group<f_Group>;
 def fsched_interblock : Flag<["-"], "fsched-interblock">,
Group<clang_ignored_f_Group>;
 def fshort_enums : Flag<["-"], "fshort-enums">, Group<f_Group>,
Flags<[CC1Option]>,
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp (revision 183239)
+++ lib/Frontend/CompilerInvocation.cpp (working copy)
@@ -473,6 +473,15 @@
       Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
   }

+  if (Arg *A = Args.getLastArg(OPT_fpcc_struct_return,
OPT_freg_struct_return)) {
+    if (A->getOption().matches(OPT_fpcc_struct_return)) {
+      Opts.PassSmallStructsConvention = 1;
+    } else {
+      assert(A->getOption().matches(OPT_freg_struct_return));
+      Opts.PassSmallStructsConvention = 2;
+    }
+  }
+
   return Success;
 }

Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp (revision 183239)
+++ lib/Driver/Tools.cpp (working copy)
@@ -2160,6 +2160,15 @@
     CmdArgs.push_back(A->getValue());
   }

+  if (Arg *A = Args.getLastArg(options::OPT_fpcc_struct_return,
options::OPT_freg_struct_return)) {
+    if (A->getOption().matches(options::OPT_fpcc_struct_return)) {
+      CmdArgs.push_back("-fpcc-struct-return");
+    } else {
+      assert(A->getOption().matches(options::OPT_freg_struct_return));
+      CmdArgs.push_back("-freg-struct-return");
+    }
+  }
+
   if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false))
     CmdArgs.push_back("-mrtd");

Index: lib/CodeGen/TargetInfo.cpp
===================================================================
--- lib/CodeGen/TargetInfo.cpp (revision 183239)
+++ lib/CodeGen/TargetInfo.cpp (working copy)
@@ -4402,7 +4402,26 @@
   return ResAddr;
 }

+static bool shouldPassSmallStructsInRegsByDefault(const llvm::Triple &Triple) {
+  assert(Triple.getArch() == llvm::Triple::x86);

+  if (Triple.isOSDarwin())
+    return true;
+
+  switch (Triple.getOS()) {
+  case llvm::Triple::Cygwin:
+  case llvm::Triple::MinGW32:
+  case llvm::Triple::AuroraUX:
+  case llvm::Triple::DragonFly:
+  case llvm::Triple::FreeBSD:
+  case llvm::Triple::OpenBSD:
+  case llvm::Triple::Bitrig:
+    return true;
+  default:
+    return false;
+  }
+}
+
 ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const {
   if (RetTy->isVoidType())
     return ABIArgInfo::getIgnore();
@@ -5420,31 +5439,32 @@
     return *(TheTargetCodeGenInfo = new TCETargetCodeGenInfo(Types));

   case llvm::Triple::x86: {
-    if (Triple.isOSDarwin())
-      return *(TheTargetCodeGenInfo =
-               new X86_32TargetCodeGenInfo(Types, true, true, false,
-                                           CodeGenOpts.NumRegisterParameters));
+    bool IsDarwinVectorABI = Triple.isOSDarwin();
+    bool IsSmallStructInRegABI = shouldPassSmallStructsInRegsByDefault(Triple);
+    bool IsWin32FloatStructABI = (Triple.getOS() == llvm::Triple::Win32);

-    switch (Triple.getOS()) {
-    case llvm::Triple::Cygwin:
-    case llvm::Triple::MinGW32:
-    case llvm::Triple::AuroraUX:
-    case llvm::Triple::DragonFly:
-    case llvm::Triple::FreeBSD:
-    case llvm::Triple::OpenBSD:
-    case llvm::Triple::Bitrig:
-      return *(TheTargetCodeGenInfo =
-               new X86_32TargetCodeGenInfo(Types, false, true, false,
-                                           CodeGenOpts.NumRegisterParameters));
+    switch (CodeGenOpts.PassSmallStructsConvention) {
+      case 0: /* use the target's default */
+        break;
+      case 1: /* -fpcc-struct-return */
+        IsSmallStructInRegABI = false;
+        break;
+      case 2: /* -freg-struct-return */
+        IsSmallStructInRegABI = true;
+        break;
+      default:
+        assert(false);
+    }

-    case llvm::Triple::Win32:
+    if (Triple.getOS() == llvm::Triple::Win32) {
       return *(TheTargetCodeGenInfo =
                new WinX86_32TargetCodeGenInfo(Types,

CodeGenOpts.NumRegisterParameters));
-
-    default:
+    } else {
       return *(TheTargetCodeGenInfo =
-               new X86_32TargetCodeGenInfo(Types, false, false, false,
+               new X86_32TargetCodeGenInfo(Types,
+                                           IsDarwinVectorABI,
IsSmallStructInRegABI,
+                                           IsWin32FloatStructABI,
                                            CodeGenOpts.NumRegisterParameters));
     }
   }



More information about the cfe-commits mailing list