[llvm-commits] [llvm-gcc-4.2] r48778 - in /llvm-gcc-4.2/trunk/gcc: llvm-abi.h llvm-convert.cpp llvm-types.cpp

Duncan Sands baldrick at free.fr
Tue Mar 25 10:02:29 PDT 2008


Author: baldrick
Date: Tue Mar 25 12:02:29 2008
New Revision: 48778

URL: http://llvm.org/viewvc/llvm-project?rev=48778&view=rev
Log:
Add infrastructure for returning scalar values
via a "shadow" sret argument, and let it handle
the vector-as-aggregate case.  I changed some
names and cleaned up whitespace while there.

Modified:
    llvm-gcc-4.2/trunk/gcc/llvm-abi.h
    llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
    llvm-gcc-4.2/trunk/gcc/llvm-types.cpp

Modified: llvm-gcc-4.2/trunk/gcc/llvm-abi.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-abi.h?rev=48778&r1=48777&r2=48778&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-abi.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-abi.h Tue Mar 25 12:02:29 2008
@@ -49,27 +49,38 @@
 /// DefaultABIClient - This is a simple implementation of the ABI client
 /// interface that can be subclassed.
 struct DefaultABIClient {
-  bool isStructReturn() { return false; }
-  
+  bool isShadowReturn() { return false; }
+
   /// HandleScalarResult - This callback is invoked if the function returns a
-  /// simple scalar result value.
+  /// simple scalar result value, which is of type RetTy.
   void HandleScalarResult(const Type *RetTy) {}
 
   /// HandleAggregateResultAsScalar - This callback is invoked if the function
   /// returns an aggregate value by bit converting it to the specified scalar
   /// type and returning that.
   void HandleAggregateResultAsScalar(const Type *ScalarTy) {}
-  
+
   /// HandleAggregateShadowArgument - This callback is invoked if the function
-  /// returns an aggregate value by using a "shadow" first parameter.  If RetPtr
-  /// is set to true, the pointer argument itself is returned from the function.
+  /// returns an aggregate value by using a "shadow" first parameter, which is
+  /// a pointer to the aggregate, of type PtrArgTy.  If RetPtr is set to true,
+  /// the pointer argument itself is returned from the function.
   void HandleAggregateShadowArgument(const PointerType *PtrArgTy, bool RetPtr){}
-  
-  
+
+  /// HandleScalarShadowArgument - This callback is invoked if the function
+  /// returns a scalar value by using a "shadow" first parameter, which is a
+  /// pointer to the scalar, of type PtrArgTy.  If RetPtr is set to true,
+  /// the pointer argument itself is returned from the function.
+  void HandleScalarShadowArgument(const PointerType *PtrArgTy, bool RetPtr) {}
+
+
   /// HandleScalarArgument - This is the primary callback that specifies an LLVM
   /// argument to pass.
   void HandleScalarArgument(const llvm::Type *LLVMTy, tree argTreeType) {}
-  
+
+  /// HandleByValArgument - This callback is invoked if the aggregate function
+  /// argument is passed by value.
+  void HandleByValArgument(const llvm::Type *LLVMTy, tree type) {}
+
   /// EnterField - Called when we're about the enter the field of a struct
   /// or union.  FieldNo is the number of the element we are entering in the
   /// LLVM Struct, StructTy is the LLVM type of the struct we are entering.
@@ -229,7 +240,7 @@
 public:
   DefaultABI(Client &c) : C(c) {}
 
-  bool isStructReturn() const { return C.isStructReturn(); }
+  bool isShadowReturn() const { return C.isShadowReturn(); }
   
   /// HandleReturnType - This is invoked by the target-independent code for the
   /// return type. It potentially breaks down the argument and invokes methods
@@ -245,7 +256,7 @@
       if (ScalarType)
         C.HandleAggregateResultAsScalar(ConvertType(ScalarType));
       else if (LLVM_SHOULD_RETURN_VECTOR_AS_SHADOW(type, isBuiltin))
-        C.HandleAggregateShadowArgument(PointerType::getUnqual(Ty), false);
+        C.HandleScalarShadowArgument(PointerType::getUnqual(Ty), false);
       else
         C.HandleScalarResult(Ty);
     } else if (Ty->isFirstClassType() || Ty == Type::VoidTy) {

Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=48778&r1=48777&r2=48778&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Tue Mar 25 12:02:29 2008
@@ -459,7 +459,15 @@
       }
       ++AI;
     }
-    
+
+    void HandleScalarShadowArgument(const PointerType *PtrArgTy, bool RetPtr) {
+      assert(AI != Builder.GetInsertBlock()->getParent()->arg_end() &&
+             "No explicit return value?");
+      AI->setName("scalar.result");
+      SET_DECL_LLVM(DECL_RESULT(FunctionDecl), AI);
+      ++AI;
+    }
+
     void HandleScalarArgument(const llvm::Type *LLVMTy, tree type) {
       Value *ArgVal = AI;
       if (ArgVal->getType() != LLVMTy) {
@@ -2255,24 +2263,8 @@
   // parameter for the chain.
   Callee = BitCastToType(Callee, PointerType::getUnqual(Ty));
 
-  Value *Result;
-  if (TREE_CODE(TREE_TYPE(exp))==VECTOR_TYPE &&
-      LLVM_SHOULD_RETURN_VECTOR_AS_SHADOW(TREE_TYPE(exp),
-                                fndecl ? DECL_BUILT_IN(fndecl) : false)) {
-    // Vectors are first class types, so we need to return a value,
-    // but this one is to be passed using sret.  Pass in a DestLoc, if
-    // there isn't one already, and return a Load from it as the value.
-    if (!DestLoc) {
-      MemRef NewLoc = CreateTempLoc(ConvertType(TREE_TYPE(exp)));
-      DestLoc = &NewLoc;
-    }
-    EmitCallOf(Callee, exp, DestLoc, PAL);
-    LoadInst *LI = Builder.CreateLoad(DestLoc->Ptr, false, "tmp");
-    Result = LI;
-  } else {
-    //EmitCall(exp, DestLoc);
-    Result = EmitCallOf(Callee, exp, DestLoc, PAL);
-  }
+  //EmitCall(exp, DestLoc);
+  Value *Result = EmitCallOf(Callee, exp, DestLoc, PAL);
 
   // If the function has the volatile bit set, then it is a "noreturn" function.
   // Output an unreachable instruction right after the function to prevent LLVM
@@ -2295,14 +2287,15 @@
     CallingConv::ID &CallingConvention;
     LLVMBuilder &Builder;
     const MemRef *DestLoc;
-    MemRef BufLoc;
+    MemRef RetBuf;
     std::vector<Value*> LocStack;
+    bool isShadowRet;
 
     FunctionCallArgumentConversion(tree exp, SmallVector<Value*, 16> &ops,
                                    CallingConv::ID &cc,
                                    LLVMBuilder &b, const MemRef *destloc)
       : CallExpression(exp), CallOperands(ops), CallingConvention(cc),
-        Builder(b), DestLoc(destloc) {
+        Builder(b), DestLoc(destloc), isShadowRet(false) {
       CallingConvention = CallingConv::C;
 #ifdef TARGET_ADJUST_LLVM_CC
       tree ftype;
@@ -2328,15 +2321,24 @@
       LocStack.clear();
     }
 
-    // CopyOutResult - If the (aggregate) return result was redirected to a
-    // buffer, copy it to the final destination.
-    void CopyOutResult(tree result_type) {
-      if (BufLoc.Ptr && DestLoc) {
-        // A buffer was used for the aggregate return result.  Copy it out now.
-        assert(ConvertType(result_type) ==
-               cast<PointerType>(BufLoc.Ptr->getType())->getElementType() &&
+    bool isShadowReturn() { return isShadowRet; }
+
+    // EmitShadowResult - If the return result was redirected to a buffer,
+    // emit it now.
+    Value *EmitShadowResult(tree type, const MemRef *DestLoc) {
+      if (!RetBuf.Ptr)
+        return 0;
+
+      if (DestLoc) {
+        // Copy out the aggregate return value now.
+        assert(ConvertType(type) ==
+               cast<PointerType>(RetBuf.Ptr->getType())->getElementType() &&
                "Inconsistent result types!");
-        TheTreeToLLVM->EmitAggregateCopy(*DestLoc, BufLoc, result_type);
+        TheTreeToLLVM->EmitAggregateCopy(*DestLoc, RetBuf, type);
+        return 0;
+      } else {
+        // Read out the scalar return value now.
+        return Builder.CreateLoad(RetBuf.Ptr, "result");
       }
     }
 
@@ -2377,9 +2379,24 @@
         // Letting the call write directly to the final destination may not be
         // safe (eg: if DestLoc aliases a parameter) and is not required - pass
         // a buffer and copy it to DestLoc after the call.
-        BufLoc = TheTreeToLLVM->CreateTempLoc(PtrArgTy->getElementType());
-        CallOperands.push_back(BufLoc.Ptr);
+        RetBuf = TheTreeToLLVM->CreateTempLoc(PtrArgTy->getElementType());
+        CallOperands.push_back(RetBuf.Ptr);
       }
+
+      // Note the use of a shadow argument.
+      isShadowRet = true;
+    }
+
+    void HandleScalarShadowArgument(const PointerType *PtrArgTy, bool RetPtr) {
+      assert(DestLoc == 0 &&
+             "Call returns a scalar but caller expects aggregate!");
+      // Create a buffer to hold the result.  The result will be loaded out of
+      // it after the call.
+      RetBuf = TheTreeToLLVM->CreateTempLoc(PtrArgTy->getElementType());
+      CallOperands.push_back(RetBuf.Ptr);
+
+      // Note the use of a shadow argument.
+      isShadowRet = true;
     }
 
     void HandleScalarArgument(const llvm::Type *LLVMTy, tree type) {
@@ -2558,13 +2575,14 @@
     EmitBlock(NextBlock);
   }
 
-  Client.CopyOutResult(TREE_TYPE(exp));
+  if (Client.isShadowReturn())
+    return Client.EmitShadowResult(TREE_TYPE(exp), DestLoc);
 
   if (Call->getType() == Type::VoidTy)
     return 0;
-  
+
   Call->setName("tmp");
-    
+
   // If the caller expects an aggregate, we have a situation where the ABI for
   // the current target specifies that the aggregate be returned in scalar
   // registers even though it is an aggregate.  We must bitconvert the scalar

Modified: llvm-gcc-4.2/trunk/gcc/llvm-types.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-types.cpp?rev=48778&r1=48777&r2=48778&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-types.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-types.cpp Tue Mar 25 12:02:29 2008
@@ -929,48 +929,61 @@
     PATypeHolder &RetTy;
     std::vector<PATypeHolder> &ArgTypes;
     unsigned &CallingConv;
-    bool isStructRet;
+    bool isShadowRet;
     bool KNRPromotion;
   public:
     FunctionTypeConversion(PATypeHolder &retty, std::vector<PATypeHolder> &AT,
                            unsigned &CC, bool KNR)
       : RetTy(retty), ArgTypes(AT), CallingConv(CC), KNRPromotion(KNR) {
       CallingConv = CallingConv::C;
-      isStructRet = false;
+      isShadowRet = false;
     }
 
-    bool isStructReturn() const { return isStructRet; }
-    
+    bool isShadowReturn() const { return isShadowRet; }
+
     /// HandleScalarResult - This callback is invoked if the function returns a
     /// simple scalar result value.
     void HandleScalarResult(const Type *RetTy) {
       this->RetTy = RetTy;
     }
-    
+
     /// HandleAggregateResultAsScalar - This callback is invoked if the function
     /// returns an aggregate value by bit converting it to the specified scalar
     /// type and returning that.
     void HandleAggregateResultAsScalar(const Type *ScalarTy) {
       RetTy = ScalarTy;
     }
-    
+
+    /// HandleShadowArgument - Handle an aggregate or scalar shadow argument.
+    void HandleShadowArgument(const PointerType *PtrArgTy, bool RetPtr) {
+      // This function either returns void or the shadow argument,
+      // depending on the target.
+      RetTy = RetPtr ? PtrArgTy : Type::VoidTy;
+
+      // In any case, there is a dummy shadow argument though!
+      ArgTypes.push_back(PtrArgTy);
+
+      // Also, note the use of a shadow argument.
+      isShadowRet = true;
+    }
+
     /// HandleAggregateShadowArgument - This callback is invoked if the function
-    /// returns an aggregate value by using a "shadow" first parameter.  If 
-    /// RetPtr is set to true, the pointer argument itself is returned from 
-    /// the function.
+    /// returns an aggregate value by using a "shadow" first parameter, which is
+    /// a pointer to the aggregate, of type PtrArgTy.  If RetPtr is set to true,
+    /// the pointer argument itself is returned from the function.
     void HandleAggregateShadowArgument(const PointerType *PtrArgTy,
                                        bool RetPtr) {
-      // If this function returns a structure by value, it either returns void
-      // or the shadow argument, depending on the target.
-      this->RetTy = RetPtr ? PtrArgTy : Type::VoidTy;
-      
-      // In any case, there is a dummy shadow argument though!
-      ArgTypes.push_back(PtrArgTy);
-      
-      // Also, switch the to C Struct Return.
-      isStructRet = true;
+      HandleShadowArgument(PtrArgTy, RetPtr);
     }
-    
+
+    /// HandleScalarShadowArgument - This callback is invoked if the function
+    /// returns a scalar value by using a "shadow" first parameter, which is a
+    /// pointer to the scalar, of type PtrArgTy.  If RetPtr is set to true,
+    /// the pointer argument itself is returned from the function.
+    void HandleScalarShadowArgument(const PointerType *PtrArgTy, bool RetPtr) {
+      HandleShadowArgument(PtrArgTy, RetPtr);
+    }
+
     void HandleScalarArgument(const llvm::Type *LLVMTy, tree type) {
       if (KNRPromotion) {
         if (LLVMTy == Type::FloatTy)
@@ -1032,12 +1045,12 @@
   if (RAttributes != ParamAttr::None)
     Attrs.push_back(ParamAttrsWithIndex::get(0, RAttributes));
 
-  // If this is a struct-return function, the dest loc is passed in as a
-  // pointer.  Mark that pointer as structret and noalias.
-  if (ABIConverter.isStructReturn())
+  // If this function returns via a shadow argument, the dest loc is passed
+  // in as a pointer.  Mark that pointer as struct-ret and noalias.
+  if (ABIConverter.isShadowReturn())
     Attrs.push_back(ParamAttrsWithIndex::get(ArgTys.size(),
                                     ParamAttr::StructRet | ParamAttr::NoAlias));
-  
+
   if (static_chain) {
     // Pass the static chain as the first parameter.
     ABIConverter.HandleArgument(TREE_TYPE(static_chain));
@@ -1113,7 +1126,7 @@
 
   // Since they write the return value through a pointer,
   // 'sret' functions cannot be 'readnone' or 'readonly'.
-  if (ABIConverter.isStructReturn())
+  if (ABIConverter.isShadowReturn())
     RAttributes &= ~(ParamAttr::ReadNone|ParamAttr::ReadOnly);
 
   // Demote 'readnone' nested functions to 'readonly' since
@@ -1128,13 +1141,13 @@
 
   if (RAttributes != ParamAttr::None)
     Attrs.push_back(ParamAttrsWithIndex::get(0, RAttributes));
-  
-  // If this is a struct-return function, the dest loc is passed in as a
-  // pointer.  Mark that pointer as structret, and noalias.
-  if (ABIConverter.isStructReturn())
+
+  // If this function returns via a shadow argument, the dest loc is passed
+  // in as a pointer.  Mark that pointer as struct-ret and noalias.
+  if (ABIConverter.isShadowReturn())
     Attrs.push_back(ParamAttrsWithIndex::get(ArgTypes.size(),
                                     ParamAttr::StructRet | ParamAttr::NoAlias));
-    
+
   if (static_chain) {
     // Pass the static chain as the first parameter.
     ABIConverter.HandleArgument(TREE_TYPE(static_chain));





More information about the llvm-commits mailing list