[llvm-commits] [llvm-gcc-4.2] r46460 - in /llvm-gcc-4.2/trunk/gcc: llvm-convert.cpp llvm-internal.h

Duncan Sands baldrick at free.fr
Mon Jan 28 12:57:25 PST 2008


Author: baldrick
Date: Mon Jan 28 14:57:24 2008
New Revision: 46460

URL: http://llvm.org/viewvc/llvm-project?rev=46460&view=rev
Log:
Fix PR1942 differently, by having the caller
take care of making a copy of the aggregate
return value rather than the callee (the previous
fix).  This is better adapted for optimization
(though the optimizations needed don't exist
yet...) and is also the way gcc does it, so is
needed for interoperability with gcc compiled
code.

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

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=46460&r1=46459&r2=46460&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Mon Jan 28 14:57:24 2008
@@ -367,8 +367,6 @@
 
   AllocaInsertionPoint = 0;
 
-  UsedSRetBuffer = false;
-
   ExceptionValue = 0;
   ExceptionSelectorValue = 0;
   FuncEHException = 0;
@@ -413,12 +411,10 @@
     LLVMBuilder Builder;
     std::vector<Value*> LocStack;
     std::vector<std::string> NameStack;
-    bool &UsedSRetBuffer;
     FunctionPrologArgumentConversion(tree FnDecl,
                                      Function::arg_iterator &ai,
-                                     const LLVMBuilder &B,
-                                     bool &SRetBuffer)
-      : FunctionDecl(FnDecl), AI(ai), Builder(B), UsedSRetBuffer(SRetBuffer) {}
+                                     const LLVMBuilder &B)
+      : FunctionDecl(FnDecl), AI(ai), Builder(B) {}
 
     void setName(const std::string &Name) {
       NameStack.push_back(Name);
@@ -446,11 +442,7 @@
       tree ResultDecl = DECL_RESULT(FunctionDecl);
       tree RetTy = TREE_TYPE(TREE_TYPE(FunctionDecl));
       if (TREE_CODE(RetTy) == TREE_CODE(TREE_TYPE(ResultDecl))) {
-        // Use a buffer for the return result.  This ensures that writes to the
-        // return value do not interfere with reads from parameters: the same
-        // aggregate might be used for the return value and as a parameter.
-        TheTreeToLLVM->EmitAutomaticVariableDecl(DECL_RESULT(FunctionDecl));
-        UsedSRetBuffer = true;
+        SET_DECL_LLVM(ResultDecl, AI);
         ++AI;
         return;
       }
@@ -666,7 +658,7 @@
   Function::arg_iterator AI = Fn->arg_begin();
 
   // Rename and alloca'ify real arguments.
-  FunctionPrologArgumentConversion Client(FnDecl, AI, Builder, UsedSRetBuffer);
+  FunctionPrologArgumentConversion Client(FnDecl, AI, Builder);
   TheLLVMABI<FunctionPrologArgumentConversion> ABIConverter(Client);
 
   // Handle the DECL_RESULT.
@@ -766,14 +758,6 @@
                              PointerType::getUnqual(Fn->getReturnType()));
       RetVal = Builder.CreateLoad(RetVal, "retval");
     }
-  } else if (UsedSRetBuffer) {
-    // A buffer was used for the aggregate return result.  Copy it out now.
-    assert(Fn->arg_begin() != Fn->arg_end() && "No struct return value?");
-    unsigned Alignment = expr_align(DECL_RESULT(FnDecl))/8;
-    bool Volatile = TREE_THIS_VOLATILE(DECL_RESULT(FnDecl));
-    MemRef BufLoc(DECL_LLVM(DECL_RESULT(FnDecl)), Alignment, false);
-    MemRef RetLoc(Fn->arg_begin(), Alignment, Volatile);
-    EmitAggregateCopy(RetLoc, BufLoc, TREE_TYPE(DECL_RESULT(FnDecl)));
   }
   if (TheDebugInfo) TheDebugInfo->EmitRegionEnd(Fn, Builder.GetInsertBlock());
   Builder.CreateRet(RetVal);
@@ -2321,6 +2305,7 @@
     CallingConv::ID &CallingConvention;
     LLVMBuilder &Builder;
     const MemRef *DestLoc;
+    MemRef BufLoc;
     std::vector<Value*> LocStack;
 
     FunctionCallArgumentConversion(tree exp, SmallVector<Value*, 16> &ops,
@@ -2352,7 +2337,19 @@
       assert(LocStack.size() == 1 && "Imbalance!");
       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() &&
+               "Inconsistent result types!");
+        TheTreeToLLVM->EmitAggregateCopy(*DestLoc, BufLoc, result_type);
+      }
+    }
+
     /// HandleScalarResult - This callback is invoked if the function returns a
     /// simple scalar result value.
     void HandleScalarResult(const Type *RetTy) {
@@ -2367,7 +2364,7 @@
     void HandleAggregateResultAsScalar(const Type *ScalarTy) {
       // There is nothing to do here.
     }
-    
+
     /// 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
@@ -2375,19 +2372,15 @@
     void HandleAggregateShadowArgument(const PointerType *PtrArgTy,
                                        bool RetPtr) {
       // We need to pass a buffer to return into.  If the caller uses the
-      // result, DestLoc will be set.  If it ignores it, it could be unset,
-      // in which case we need to create a dummy buffer.
-      // FIXME: The alignment and volatility of the buffer are being ignored!
-      Value *DestPtr;
-      if (DestLoc == 0) {
-        DestPtr = TheTreeToLLVM->CreateTemporary(PtrArgTy->getElementType());
-      } else {
-        DestPtr = DestLoc->Ptr;
-        assert(PtrArgTy == DestPtr->getType());
-      }
-      CallOperands.push_back(DestPtr);
+      // result, DestLoc will be set.  Since DestLoc may alias a parameter,
+      // the result needs to be stored in a buffer then copied to DestLoc
+      // after the call.  If DestLoc is not set then the result is unused,
+      // in which case we need to create a dummy buffer but not copy it out.
+      assert(!DestLoc || PtrArgTy == DestLoc->Ptr->getType());
+      BufLoc = TheTreeToLLVM->CreateTempLoc(PtrArgTy->getElementType());
+      CallOperands.push_back(BufLoc.Ptr);
     }
-    
+
     void HandleScalarArgument(const llvm::Type *LLVMTy, tree type) {
       assert(!LocStack.empty());
       Value *Loc = LocStack.back();
@@ -2556,7 +2549,9 @@
     cast<InvokeInst>(Call)->setParamAttrs(PAL);
     EmitBlock(NextBlock);
   }
-  
+
+  Client.CopyOutResult(TREE_TYPE(exp));
+
   if (Call->getType() == Type::VoidTy)
     return 0;
   

Modified: llvm-gcc-4.2/trunk/gcc/llvm-internal.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-internal.h?rev=46460&r1=46459&r2=46460&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-internal.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-internal.h Mon Jan 28 14:57:24 2008
@@ -286,10 +286,6 @@
   // and managed by CreateTemporary.
   Instruction *AllocaInsertionPoint;
 
-  // UsedSRetBuffer - Whether a buffer was used for an aggregate return value.
-  // If so, it needs copying out when the function returns.
-  bool UsedSRetBuffer;
-
   //===---------------------- Exception Handling --------------------------===//
 
   /// LandingPads - The landing pad for a given EH region.
@@ -390,7 +386,12 @@
   /// instruction's type is a pointer to the specified type.
   AllocaInst *CreateTemporary(const Type *Ty);
 
-  void EmitAutomaticVariableDecl(tree_node *decl);
+  /// CreateTempLoc - Like CreateTemporary, but returns a MemRef.
+  MemRef CreateTempLoc(const Type *Ty);
+
+  /// EmitAggregateCopy - Copy the elements from SrcLoc to DestLoc, using the
+  /// GCC type specified by GCCType to know which elements to copy.
+  void EmitAggregateCopy(MemRef DestLoc, MemRef SrcLoc, tree_node *GCCType);
 
 private: // Helper functions.
 
@@ -412,10 +413,6 @@
   /// the previous block falls through into it, add an explicit branch.
   void EmitBlock(BasicBlock *BB);
   
-  /// EmitAggregateCopy - Copy the elements from SrcLoc to DestLoc, using the
-  /// GCC type specified by GCCType to know which elements to copy.
-  void EmitAggregateCopy(MemRef DestLoc, MemRef SrcLoc, tree_node *GCCType);
-
   /// EmitAggregateZero - Zero the elements of DestLoc.
   ///
   void EmitAggregateZero(MemRef DestLoc, tree_node *GCCType);
@@ -449,8 +446,7 @@
   BasicBlock *getPostPad(unsigned RegionNo);
 
 private:
-  /// CreateTempLoc - Like CreateTemporary, but returns a MemRef.
-  MemRef CreateTempLoc(const Type *Ty);
+  void EmitAutomaticVariableDecl(tree_node *decl);
 
   /// isNoopCast - Return true if a cast from V to Ty does not change any bits.
   ///





More information about the llvm-commits mailing list