mkuper created this revision.
mkuper added reviewers: rnk, rafael.
mkuper added a subscriber: cfe-commits.
mkuper added a dependency: D13977: [X86] Add elfiamcu triple support, and a 
workaround for PR3997.
Herald added a subscriber: aemerson.

The  MCU psABI has a calling convention that is somewhat, but not quite, like 
-mregparm 3.
This adds support for this calling convention.

It depends on D13977 which introduces MCU triple support.

http://reviews.llvm.org/D13978

Files:
  lib/CodeGen/TargetInfo.cpp
  test/CodeGen/x86_32-arguments-iamcu.c

Index: lib/CodeGen/TargetInfo.cpp
===================================================================
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -799,6 +799,7 @@
   bool IsRetSmallStructInRegABI;
   bool IsWin32StructABI;
   bool IsSoftFloatABI;
+  bool IsMCUABI;
   unsigned DefaultNumRegisterParameters;
 
   static bool isRegisterSize(unsigned Size) {
@@ -848,22 +849,24 @@
 
   X86_32ABIInfo(CodeGen::CodeGenTypes &CGT, bool DarwinVectorABI,
                 bool RetSmallStructInRegABI, bool Win32StructABI,
-                unsigned NumRegisterParameters, bool SoftFloatABI)
+                unsigned NumRegisterParameters, bool SoftFloatABI,
+                bool MCUABI)
     : ABIInfo(CGT), IsDarwinVectorABI(DarwinVectorABI),
       IsRetSmallStructInRegABI(RetSmallStructInRegABI), 
       IsWin32StructABI(Win32StructABI),
-      IsSoftFloatABI(SoftFloatABI),
+      IsSoftFloatABI(SoftFloatABI), IsMCUABI(MCUABI),
       DefaultNumRegisterParameters(NumRegisterParameters) {}
 };
 
 class X86_32TargetCodeGenInfo : public TargetCodeGenInfo {
 public:
   X86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool DarwinVectorABI,
                           bool RetSmallStructInRegABI, bool Win32StructABI,
-                          unsigned NumRegisterParameters, bool SoftFloatABI)
+                          unsigned NumRegisterParameters, bool SoftFloatABI,
+                          bool MCUABI)
       : TargetCodeGenInfo(new X86_32ABIInfo(
             CGT, DarwinVectorABI, RetSmallStructInRegABI, Win32StructABI,
-            NumRegisterParameters, SoftFloatABI)) {}
+            NumRegisterParameters, SoftFloatABI, MCUABI)) {}
 
   static bool isStructReturnInRegABI(
       const llvm::Triple &Triple, const CodeGenOptions &Opts);
@@ -986,7 +989,7 @@
 }
 
 /// shouldReturnTypeInRegister - Determine if the given type should be
-/// returned in a register (for the Darwin ABI).
+/// returned in a register (for the Darwin and MCU ABI).
 bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty,
                                                ASTContext &Context) const {
   uint64_t Size = Context.getTypeSize(Ty);
@@ -1226,9 +1229,18 @@
   if (SizeInRegs == 0)
     return false;
 
-  if (SizeInRegs > State.FreeRegs) {
-    State.FreeRegs = 0;
-    return false;
+  if (!IsMCUABI) {
+    if (SizeInRegs > State.FreeRegs) {
+      State.FreeRegs = 0;
+      return false;
+    }
+  } else {
+    // The MCU psABI allows passing parameters in-reg even if there are
+    // earlier, parameters that are passed on the stack. Also,
+    // it does not allow passing >8-byte structs in-register,
+    // even if there are 3 free registers available.
+    if (SizeInRegs > State.FreeRegs || SizeInRegs > 2)
+      return false;
   }
 
   State.FreeRegs -= SizeInRegs;
@@ -1372,6 +1384,8 @@
     State.FreeSSERegs = 6;
   } else if (FI.getHasRegParm())
     State.FreeRegs = FI.getRegParm();
+  else if (IsMCUABI)
+    State.FreeRegs = 3;
   else
     State.FreeRegs = DefaultNumRegisterParameters;
 
@@ -1520,7 +1534,7 @@
     return true;
   }
 
-  if (Triple.isOSDarwin())
+  if (Triple.isOSDarwin() || Triple.isEnvironmentIAMCU())
     return true;
 
   switch (Triple.getOS()) {
@@ -1889,7 +1903,7 @@
         bool DarwinVectorABI, bool RetSmallStructInRegABI, bool Win32StructABI,
         unsigned NumRegisterParameters)
     : X86_32TargetCodeGenInfo(CGT, DarwinVectorABI, RetSmallStructInRegABI,
-        Win32StructABI, NumRegisterParameters, false) {}
+        Win32StructABI, NumRegisterParameters, false, false) {}
 
   void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
                            CodeGen::CodeGenModule &CGM) const override;
@@ -7402,7 +7416,7 @@
       return *(TheTargetCodeGenInfo = new X86_32TargetCodeGenInfo(
                    Types, IsDarwinVectorABI, RetSmallStructInRegABI,
                    IsWin32FloatStructABI, CodeGenOpts.NumRegisterParameters,
-                   CodeGenOpts.FloatABI == "soft"));
+                   CodeGenOpts.FloatABI == "soft", Triple.isEnvironmentIAMCU()));
     }
   }
 
Index: test/CodeGen/x86_32-arguments-iamcu.c
===================================================================
--- test/CodeGen/x86_32-arguments-iamcu.c
+++ test/CodeGen/x86_32-arguments-iamcu.c
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -w -triple i386-pc-elfiamcu -mfloat-abi soft -emit-llvm -o - %s | FileCheck %s
+
+// CHECK-LABEL: define void @ints(i32 inreg %a, i32 inreg %b, i32 inreg %c, i32 %d)
+void ints(int a, int b, int c, int d) {}
+
+// CHECK-LABEL: define void @floats(float inreg %a, float inreg %b, float inreg %c, float %d)
+void floats(float a, float b, float c, float d) {}
+
+// CHECK-LABEL: define void @mixed(i32 inreg %a, float inreg %b, i32 inreg %c, float %d)
+void mixed(int a, float b, int c, float d) {}
+
+// CHECK-LABEL: define void @doubles(double inreg %d1, double %d2)
+void doubles(double d1, double d2) {}
+
+// CHECK-LABEL: define void @mixedDoubles(i32 inreg %a, double inreg %d1)
+void mixedDoubles(int a, double d1) {}
+
+typedef struct st4_t {
+  int a;
+} st4_t;
+
+typedef struct st5_t {
+  int a;
+  char b;
+} st5_t;
+
+typedef  struct st12_t {
+  int a;
+  int b;
+  int c;
+} st12_t;
+
+// CHECK-LABEL: define void @smallStructs(i32 inreg %st1.coerce, i32 inreg %st2.coerce, i32 inreg %st3.coerce)
+void smallStructs(st4_t st1, st4_t st2, st4_t st3) {}
+
+// CHECK-LABEL: define void @paddedStruct(i32 inreg %i1, i32 inreg %st.coerce0, i32 inreg %st.coerce1, i32 %st4.0)
+void paddedStruct(int i1, st5_t st, st4_t st4) {}
+
+// CHECK-LABEL: define void @largeStruct(i32 %st.0, i32 %st.1, i32 %st.2)
+void largeStruct(st12_t st) {}
+
+// CHECK-LABEL: define void @largeStructMiddle(i32 inreg %i1, i32 %st.0, i32 %st.1, i32 %st.2, i32 inreg %i2, i32 inreg %i3)
+void largeStructMiddle(int i1, st12_t st, int i2, int i3) {}
+
+// CHECK-LABEL: define i32 @retSmallStruct(i32 inreg %r.coerce)
+st4_t retSmallStruct(st4_t r) { return r; }
+
+// CHECK-LABEL: define i64 @retPaddedStruct(i32 inreg %r.coerce0, i32 inreg %r.coerce1)
+st5_t retPaddedStruct(st5_t r) { return r; }
+
+// CHECK-LABEL: define void @retLargeStruct(%struct.st12_t* inreg noalias sret %agg.result, i32 inreg %i1, i32 %r.0, i32 %r.1, i32 %r.2)
+st12_t retLargeStruct(int i1, st12_t r) { return r; }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to