Hello, Everyone.

Attached patch will enable llvm-gcc to use sret & inreg attributes.

-- 
With best regards, Anton Korobeynikov.

Faculty of Mathematics & Mechanics, Saint Petersburg State University.

diff -r 19e687420e52 gcc/config/i386/cygming.h
--- a/gcc/config/i386/cygming.h	Sun Jan 28 02:52:06 2007 +0300
+++ b/gcc/config/i386/cygming.h	Sun Jan 28 17:55:48 2007 +0300
@@ -429,6 +429,8 @@ extern int i386_pe_dllimport_p (tree);
 #endif
 
 /* APPLE LOCAL begin LLVM */
+#ifdef ENABLE_LLVM
+
 /* LLVM specific stuff for supporting dllimport & dllexport linkage output */
 
 #define TARGET_ADJUST_LLVM_LINKAGE(GV, decl)            \
@@ -439,18 +441,11 @@ extern int i386_pe_dllimport_p (tree);
       (GV)->setLinkage(GlobalValue::DLLExportLinkage);  \
     }                                                   \
   }
-  
-/* LLVM specific stuff for supporting calling convention output */
-
-#define TARGET_ADJUST_LLVM_CC(CC, type)                         \
-  {                                                             \
-    tree type_attributes = TYPE_ATTRIBUTES (type);              \
-    if (lookup_attribute ("stdcall", type_attributes)) {        \
-      CC = CallingConv::X86_StdCall;                            \
-    } else if (lookup_attribute("fastcall", type_attributes)) { \
-      CC = CallingConv::X86_FastCall;                           \
-    }                                                           \
-  }                                                             \
-    
+
+/* Add general target specific stuff */
+#include "llvm-i386-target.h"
+
 /* APPLE LOCAL end LLVM */
+
+#endif
                                                           
diff -r 19e687420e52 gcc/config/i386/darwin.h
--- a/gcc/config/i386/darwin.h	Sun Jan 28 02:52:06 2007 +0300
+++ b/gcc/config/i386/darwin.h	Sun Jan 28 17:57:02 2007 +0300
@@ -343,3 +343,13 @@ extern void ix86_darwin_init_expanders (
 #undef TARGET_DEEP_BRANCH_PREDICTION
 #define TARGET_DEEP_BRANCH_PREDICTION ((m_PPRO | m_K6 | m_ATHLON_K8 | m_PENT4) & TUNEMASK)
 /* APPLE LOCAL end 4106131 */
+
+/* APPLE LOCAL begin LLVM */
+#ifdef ENABLE_LLVM
+
+/* Add general target specific stuff */
+#include "llvm-i386-target.h"
+
+/* APPLE LOCAL end LLVM */
+
+#endif
diff -r 19e687420e52 gcc/config/i386/linux.h
--- a/gcc/config/i386/linux.h	Sun Jan 28 02:52:06 2007 +0300
+++ b/gcc/config/i386/linux.h	Sun Jan 28 17:57:05 2007 +0300
@@ -190,11 +190,15 @@ Boston, MA 02111-1307, USA.  */
 #ifdef ENABLE_LLVM
 
 /* Yes, we're supporting PIC codegen for X86-Linux-ELF target! */
-
 #define LLVM_SET_TARGET_OPTIONS(argvec)              \
   if (flag_pic)                                      \
     argvec.push_back ("--relocation-model=pic");     \
   else                                               \
     argvec.push_back ("--relocation-model=static");
-#endif
+
+/* Add general target specific stuff */
+#include "llvm-i386-target.h"
+
 /* APPLE LOCAL end LLVM */
+
+#endif
diff -r 19e687420e52 gcc/llvm-abi.h
--- a/gcc/llvm-abi.h	Sun Jan 28 02:52:06 2007 +0300
+++ b/gcc/llvm-abi.h	Fri Jan 26 11:31:36 2007 +0300
@@ -47,6 +47,8 @@ extern "C" {
 /// DefaultABIClient - This is a simple implementation of the ABI client
 /// interface that can be subclassed.
 struct DefaultABIClient {
+  bool isStructReturn() { return false; }
+  
   /// HandleScalarResult - This callback is invoked if the function returns a
   /// simple scalar result value.
   void HandleScalarResult(const Type *RetTy) {}
@@ -136,6 +138,8 @@ protected:
   Client &C;
 public:
   DefaultABI(Client &c) : C(c) {}
+
+  bool isStructReturn() const { return C.isStructReturn(); }
   
   /// HandleReturnType - This is invoked by the target-independent code for the
   /// return type. It potentially breaks down the argument and invokes methods
diff -r 19e687420e52 gcc/llvm-convert.cpp
--- a/gcc/llvm-convert.cpp	Sun Jan 28 02:52:06 2007 +0300
+++ b/gcc/llvm-convert.cpp	Sun Jan 28 02:53:45 2007 +0300
@@ -1876,6 +1876,7 @@ namespace {
     tree CallExpression;
     std::vector<Value*> &CallOperands;
     CallingConv::ID &CallingConvention;
+    bool isStructRet;
     BasicBlock *CurBB;
     Value *DestLoc;
     std::vector<Value*> LocStack;
@@ -1886,6 +1887,7 @@ namespace {
       : CallExpression(exp), CallOperands(ops), CallingConvention(cc),
         CurBB(bb), DestLoc(destloc) {
       CallingConvention = CallingConv::C;
+      isStructRet = false;
 #ifdef TARGET_ADJUST_LLVM_CC
       tree ftype;
       if (tree fdecl = get_callee_fndecl(exp)) {
@@ -1931,8 +1933,8 @@ namespace {
     /// function.
     void HandleAggregateShadowArgument(const PointerType *PtrArgTy,
                                        bool RetPtr) {
-      // Make sure this call is marked as csret calling convention.
-      CallingConvention = CallingConv::CSRet;
+      // Make sure this call is marked as 'struct return'.
+      isStructRet = true;
       
       // If the front-end has already made the argument explicit, don't do it
       // again.
diff -r 19e687420e52 gcc/llvm-types.cpp
--- a/gcc/llvm-types.cpp	Sun Jan 28 02:52:06 2007 +0300
+++ b/gcc/llvm-types.cpp	Fri Jan 26 23:32:03 2007 +0300
@@ -468,13 +468,17 @@ namespace {
     const Type *&RetTy;
     std::vector<const Type*> &ArgTypes;
     unsigned &CallingConv;
+    bool isStructRet;
     bool KNRPromotion;
   public:
     FunctionTypeConversion(const Type *&retty, std::vector<const Type*> &AT,
                            unsigned &CC, bool KNR)
       : RetTy(retty), ArgTypes(AT), CallingConv(CC), KNRPromotion(KNR) {
       CallingConv = CallingConv::C;
-    }
+      isStructRet = false;
+    }
+
+    bool isStructReturn() const { return isStructRet; }
     
     /// HandleScalarResult - This callback is invoked if the function returns a
     /// simple scalar result value.
@@ -502,8 +506,8 @@ namespace {
       // In any case, there is a dummy shadow argument though!
       ArgTypes.push_back(PtrArgTy);
       
-      // Also, switch the calling convention to C Struct Return.
-      CallingConv = CallingConv::CSRet;
+      // Also, switch the to C Struct Return.
+      isStructRet = true;
     }
     
     void HandleScalarArgument(const llvm::Type *LLVMTy, tree type) {
@@ -584,36 +588,68 @@ const FunctionType *TypeConverter::Conve
   // the function will be correctly sign or zero extended to 32-bits by
   // the LLVM code gen.
   FunctionType::ParamAttrsList ParamAttrs;
-  if (CallingConv == CallingConv::C || CallingConv == CallingConv::CSRet) {
+  unsigned RAttributes = FunctionType::NoAttributeSet;
+  if (CallingConv == CallingConv::C) {
     tree ResultTy = TREE_TYPE(type);  
     if (TREE_CODE(ResultTy) == BOOLEAN_TYPE) {
       if (TREE_INT_CST_LOW(TYPE_SIZE(ResultTy)) < INT_TYPE_SIZE)
-        ParamAttrs.push_back(FunctionType::ZExtAttribute);
-    } else if (TREE_CODE(ResultTy) == INTEGER_TYPE && 
-             TREE_INT_CST_LOW(TYPE_SIZE(ResultTy)) < INT_TYPE_SIZE)
-      if (TYPE_UNSIGNED(ResultTy))
-        ParamAttrs.push_back(FunctionType::ZExtAttribute);
-      else 
-        ParamAttrs.push_back(FunctionType::SExtAttribute);
-    else
-      ParamAttrs.push_back(FunctionType::NoAttributeSet);
-    tree Args = TYPE_ARG_TYPES(type);
-    unsigned Idx = 1;
-    for (; Args && TREE_VALUE(Args) != void_type_node; Args = TREE_CHAIN(Args)){
-      tree Ty = TREE_VALUE(Args);
+        RAttributes |= FunctionType::ZExtAttribute;
+    } else {
+      if (TREE_CODE(ResultTy) == INTEGER_TYPE && 
+          TREE_INT_CST_LOW(TYPE_SIZE(ResultTy)) < INT_TYPE_SIZE)
+        if (TYPE_UNSIGNED(ResultTy))
+          RAttributes |= FunctionType::ZExtAttribute;
+        else 
+          RAttributes |= FunctionType::SExtAttribute;
+    }
+  }
+  ParamAttrs.push_back(FunctionType::ParameterAttributes(RAttributes));
+  
+  unsigned Idx = 1;
+  bool isFirstArg = true;
+
+  int lparam = 0;
+#ifdef LLVM_TARGET_ENABLE_REGPARM
+  LLVM_TARGET_INIT_REGPARM(lparam, type);
+#endif // LLVM_TARGET_ENABLE_REGPARM
+
+  for (tree Args = TYPE_ARG_TYPES(type);
+       Args && TREE_VALUE(Args) != void_type_node;
+       Args = TREE_CHAIN(Args)) {
+    unsigned Attributes = FunctionType::NoAttributeSet;
+    tree Ty = TREE_VALUE(Args);
+    
+    if (CallingConv == CallingConv::C) {
       if (TREE_CODE(Ty) == BOOLEAN_TYPE) {
         if (TREE_INT_CST_LOW(TYPE_SIZE(Ty)) < INT_TYPE_SIZE)
-          ParamAttrs.push_back(FunctionType::ZExtAttribute);
+          Attributes |= FunctionType::ZExtAttribute;
       } else if (TREE_CODE(Ty) == INTEGER_TYPE && 
-                 TREE_INT_CST_LOW(TYPE_SIZE(Ty)) < INT_TYPE_SIZE)
+                 TREE_INT_CST_LOW(TYPE_SIZE(Ty)) < INT_TYPE_SIZE) {
         if (TYPE_UNSIGNED(Ty))
-          ParamAttrs.push_back(FunctionType::ZExtAttribute);
-        else 
-          ParamAttrs.push_back(FunctionType::SExtAttribute);
-      else
-        ParamAttrs.push_back(FunctionType::NoAttributeSet);
-      Idx++;
-    }
+          Attributes |= FunctionType::ZExtAttribute;
+        else
+          Attributes |= FunctionType::SExtAttribute;
+      }
+    }
+
+    // Handle struct return
+    if (isFirstArg) {
+      if (ABIConverter.isStructReturn()) {
+        Attributes |= FunctionType::StructRetAttribute;
+        //printf("Struct return!\n");
+      }
+      isFirstArg = false;
+    }
+
+#ifdef LLVM_TARGET_ENABLE_REGPARM
+    if (TREE_CODE(Ty) == INTEGER_TYPE || TREE_CODE(Ty) == POINTER_TYPE)
+      LLVM_ADJUST_REGPARM_ATTRIBUTE(Attributes, TREE_INT_CST_LOW(TYPE_SIZE(Ty)),
+                                    isVarArg, lparam);
+#endif // LLVM_TARGET_ENABLE_REGPARM
+
+    Idx++;
+
+    ParamAttrs.push_back(FunctionType::ParameterAttributes(Attributes));
   }
   return FunctionType::get(RetTy, ArgTypes, isVarArg, ParamAttrs);
 }
--- /dev/null                                   2000-10-22 01:01:00.000000000 +0400
+++ a/gcc/config/i386/llvm-i386-target.h	2007-01-28 17:54:06.349945062 +0300
@@ -0,0 +1,61 @@
+/* APPLE LOCAL begin LLVM (ENTIRE FILE!)  */
+/* Some target-specific hooks for gcc->llvm conversion
+Copyright (C) 2007 Free Software Foundation, Inc.
+Contributed by Anton Korobeynikov ([EMAIL PROTECTED])
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+/* LLVM specific stuff for supporting calling convention output */
+#define TARGET_ADJUST_LLVM_CC(CC, type)                         \
+  {                                                             \
+    tree type_attributes = TYPE_ATTRIBUTES (type);              \
+    if (lookup_attribute ("stdcall", type_attributes)) {        \
+      CC = CallingConv::X86_StdCall;                            \
+    } else if (lookup_attribute("fastcall", type_attributes)) { \
+      CC = CallingConv::X86_FastCall;                           \
+    }                                                           \
+  }                                                             \
+
+/* LLVM specific stuff for converting gcc's `regparm` attribute to LLVM's
+   `inreg` parameter attribute */
+#define LLVM_TARGET_ENABLE_REGPARM
+
+#define LLVM_TARGET_INIT_REGPARM(local_regparm, type)           \
+  {                                                             \
+    tree attr;                                                  \
+    local_regparm = ix86_regparm;                               \
+    attr = lookup_attribute ("regparm",                         \
+                              TYPE_ATTRIBUTES (type));          \
+    if (attr) {                                                 \
+      local_regparm = TREE_INT_CST_LOW (TREE_VALUE              \
+                                        (TREE_VALUE (attr)));   \
+    }                                                           \
+  }
+
+#define LLVM_ADJUST_REGPARM_ATTRIBUTE(Attribute, Size,          \
+                                      isVarArg, local_regparm)  \
+  {                                                             \
+    if (!isVarArg && !TARGET_64BIT) {                           \
+      int words = (Size + BITS_PER_WORD - 1) / BITS_PER_WORD;   \
+      local_regparm -= words;                                   \
+      if (local_regparm>=0) {                                   \
+        Attribute |= FunctionType::InRegAttribute;              \
+      } else                                                    \
+        local_regparm = 0;                                      \
+    }                                                           \
+  }
_______________________________________________
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

Reply via email to