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

Duncan Sands baldrick at free.fr
Fri Jan 25 09:36:35 PST 2008


Author: baldrick
Date: Fri Jan 25 11:36:35 2008
New Revision: 46356

URL: http://llvm.org/viewvc/llvm-project?rev=46356&view=rev
Log:
Fix PR1942.  When returning an aggregate result,
create a temporary to hold the result, and copy
it out when returning.

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=46356&r1=46355&r2=46356&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Fri Jan 25 11:36:35 2008
@@ -367,6 +367,8 @@
 
   AllocaInsertionPoint = 0;
 
+  UsedSRetBuffer = false;
+
   ExceptionValue = 0;
   ExceptionSelectorValue = 0;
   FuncEHException = 0;
@@ -411,11 +413,13 @@
     LLVMBuilder Builder;
     std::vector<Value*> LocStack;
     std::vector<std::string> NameStack;
+    bool &UsedSRetBuffer;
     FunctionPrologArgumentConversion(tree FnDecl,
                                      Function::arg_iterator &ai,
-                                     const LLVMBuilder &B)
-      : FunctionDecl(FnDecl), AI(ai), Builder(B) {}
-    
+                                     const LLVMBuilder &B,
+                                     bool &SRetBuffer)
+      : FunctionDecl(FnDecl), AI(ai), Builder(B), UsedSRetBuffer(SRetBuffer) {}
+
     void setName(const std::string &Name) {
       NameStack.push_back(Name);
     }
@@ -435,23 +439,29 @@
       // instead.
       assert(AI != Builder.GetInsertBlock()->getParent()->arg_end() &&
              "No explicit return value?");
+      assert(AI == Builder.GetInsertBlock()->getParent()->arg_begin() &&
+             "Struct return is not first argument!");
       AI->setName("agg.result");
-        
+
       tree ResultDecl = DECL_RESULT(FunctionDecl);
       tree RetTy = TREE_TYPE(TREE_TYPE(FunctionDecl));
       if (TREE_CODE(RetTy) == TREE_CODE(TREE_TYPE(ResultDecl))) {
-        SET_DECL_LLVM(ResultDecl, AI);
+        // 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;
         ++AI;
         return;
       }
-      
+
       // Otherwise, this must be something returned with NRVO.
       assert(TREE_CODE(TREE_TYPE(ResultDecl)) == REFERENCE_TYPE &&
              "Not type match and not passing by reference?");
       // Create an alloca for the ResultDecl.
       Value *Tmp = TheTreeToLLVM->CreateTemporary(AI->getType());
       Builder.CreateStore(AI, Tmp);
-      
+
       SET_DECL_LLVM(ResultDecl, Tmp);
       if (TheDebugInfo) {
         TheDebugInfo->EmitDeclare(ResultDecl,
@@ -656,7 +666,7 @@
   Function::arg_iterator AI = Fn->arg_begin();
 
   // Rename and alloca'ify real arguments.
-  FunctionPrologArgumentConversion Client(FnDecl, AI, Builder);
+  FunctionPrologArgumentConversion Client(FnDecl, AI, Builder, UsedSRetBuffer);
   TheLLVMABI<FunctionPrologArgumentConversion> ABIConverter(Client);
 
   // Handle the DECL_RESULT.
@@ -756,6 +766,14 @@
                              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);
@@ -2675,20 +2693,9 @@
     // Non-bitfield aggregate value.
     MemRef NewLoc(LV.Ptr, Alignment, isVolatile);
 
-    if (DestLoc) {
-      Emit(TREE_OPERAND(exp, 1), &NewLoc);
+    Emit(TREE_OPERAND(exp, 1), &NewLoc);
+    if (DestLoc)
       EmitAggregateCopy(*DestLoc, NewLoc, TREE_TYPE(exp));
-    } else if (TREE_CODE(TREE_OPERAND(exp, 0)) != RESULT_DECL) {
-      Emit(TREE_OPERAND(exp, 1), &NewLoc);
-    } else {
-      // We do this for stores into RESULT_DECL because it is possible for that
-      // memory area to overlap with the object being stored into it; see 
-      // gcc.c-torture/execute/20010124-1.c.
-
-      MemRef Tmp = CreateTempLoc(ConvertType(TREE_TYPE(TREE_OPERAND(exp,1))));
-      Emit(TREE_OPERAND(exp, 1), &Tmp);
-      EmitAggregateCopy(NewLoc, Tmp, TREE_TYPE(TREE_OPERAND(exp,1)));
-    }
     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=46356&r1=46355&r2=46356&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-internal.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-internal.h Fri Jan 25 11:36:35 2008
@@ -285,7 +285,11 @@
   // AllocaInsertionPoint - Place to insert alloca instructions.  Lazily created
   // 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.
@@ -386,6 +390,8 @@
   /// instruction's type is a pointer to the specified type.
   AllocaInst *CreateTemporary(const Type *Ty);
 
+  void EmitAutomaticVariableDecl(tree_node *decl);
+
 private: // Helper functions.
 
   /// StartFunctionBody - Start the emission of 'fndecl', outputing all
@@ -446,8 +452,6 @@
   /// 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.
   ///
   static bool isNoopCast(Value *V, const Type *Ty);





More information about the llvm-commits mailing list