]> granicus.if.org Git - clang/commitdiff
Implement support for coercion to wider types during ABI handling.
authorDaniel Dunbar <daniel@zuster.org>
Tue, 27 Jan 2009 01:36:03 +0000 (01:36 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Tue, 27 Jan 2009 01:36:03 +0000 (01:36 +0000)
 - Code quality is poor, but simple.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63083 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCall.cpp

index cd781781f9192a8423db8c93ac415670f9053589..9e632c0e272eadba365516c79a93e9cdd3d3699d 100644 (file)
@@ -22,6 +22,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Attributes.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Target/TargetData.h"
 using namespace clang;
 using namespace CodeGen;
 
@@ -935,6 +936,71 @@ void CodeGenFunction::EmitFunctionProlog(llvm::Function *Fn,
   assert(AI == Fn->arg_end() && "Argument mismatch!");
 }
 
+/// CreateCoercedLoad - Create a load from \arg SrcPtr interpreted as
+/// a pointer to an object of type \arg Ty.
+///
+/// This safely handles the case when the src type is smaller than the
+/// destination type; in this situation the values of bits which not
+/// present in the src are undefined.
+static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr,
+                                      const llvm::Type *Ty,
+                                      CodeGenFunction &CGF) {
+  const llvm::Type *SrcTy = 
+    cast<llvm::PointerType>(SrcPtr->getType())->getElementType();
+  unsigned SrcSize = CGF.CGM.getTargetData().getTypePaddedSize(SrcTy);
+  unsigned DstSize = CGF.CGM.getTargetData().getTypePaddedSize(Ty);
+
+  // If load is legal, just bitcase the src pointer.
+  if (SrcSize == DstSize) {
+    llvm::Value *Casted =
+      CGF.Builder.CreateBitCast(SrcPtr, llvm::PointerType::getUnqual(Ty));
+    return CGF.Builder.CreateLoad(Casted);
+  } else {
+    assert(SrcSize < DstSize && "Coercion is losing source bits!");
+
+    // Otherwise do coercion through memory. This is stupid, but
+    // simple.
+    llvm::Value *Tmp = CGF.CreateTempAlloca(Ty);
+    llvm::Value *Casted = 
+      CGF.Builder.CreateBitCast(Tmp, llvm::PointerType::getUnqual(SrcTy));
+    CGF.Builder.CreateStore(CGF.Builder.CreateLoad(SrcPtr), Casted);
+    return CGF.Builder.CreateLoad(Tmp);
+  }
+}
+
+/// CreateCoercedStore - Create a store to \arg DstPtr from \arg Src,
+/// where the source and destination may have different types.
+///
+/// This safely handles the case when the src type is larger than the
+/// destination type; the upper bits of the src will be lost.
+static void CreateCoercedStore(llvm::Value *Src,
+                               llvm::Value *DstPtr,
+                               CodeGenFunction &CGF) {
+  const llvm::Type *SrcTy = Src->getType();
+  const llvm::Type *DstTy = 
+    cast<llvm::PointerType>(DstPtr->getType())->getElementType();
+
+  unsigned SrcSize = CGF.CGM.getTargetData().getTypePaddedSize(SrcTy);
+  unsigned DstSize = CGF.CGM.getTargetData().getTypePaddedSize(DstTy);
+
+  // If store is legal, just bitcase the src pointer.
+  if (SrcSize == DstSize) {
+    llvm::Value *Casted =
+      CGF.Builder.CreateBitCast(DstPtr, llvm::PointerType::getUnqual(SrcTy));
+    CGF.Builder.CreateStore(Src, Casted);
+  } else {
+    assert(SrcSize > DstSize && "Coercion is missing bits!");
+    
+    // Otherwise do coercion through memory. This is stupid, but
+    // simple.
+    llvm::Value *Tmp = CGF.CreateTempAlloca(SrcTy);
+    CGF.Builder.CreateStore(Src, Tmp);
+    llvm::Value *Casted = 
+      CGF.Builder.CreateBitCast(Tmp, llvm::PointerType::getUnqual(DstTy));
+    CGF.Builder.CreateStore(CGF.Builder.CreateLoad(Casted), DstPtr);
+  }
+}
+
 void CodeGenFunction::EmitFunctionEpilog(QualType RetTy, 
                                          llvm::Value *ReturnValue) {
   llvm::Value *RV = 0;
@@ -965,9 +1031,7 @@ void CodeGenFunction::EmitFunctionEpilog(QualType RetTy,
       break;
       
     case ABIArgInfo::Coerce: {
-      const llvm::Type *CoerceToPTy = 
-        llvm::PointerType::getUnqual(RetAI.getCoerceToType());
-      RV = Builder.CreateLoad(Builder.CreateBitCast(ReturnValue, CoerceToPTy));
+      RV = CreateCoercedLoad(ReturnValue, RetAI.getCoerceToType(), *this);
       break;
     }
 
@@ -1073,10 +1137,8 @@ RValue CodeGenFunction::EmitCall(llvm::Value *Callee,
     return RValue::get(0);
 
   case ABIArgInfo::Coerce: {
-    const llvm::Type *CoerceToPTy = 
-      llvm::PointerType::getUnqual(RetAI.getCoerceToType());
-    llvm::Value *V = CreateTempAlloca(ConvertType(RetTy), "tmp");
-    Builder.CreateStore(CI, Builder.CreateBitCast(V, CoerceToPTy));
+    llvm::Value *V = CreateTempAlloca(ConvertType(RetTy), "coerce");
+    CreateCoercedStore(CI, V, *this);
     if (RetTy->isAnyComplexType())
       return RValue::getComplex(LoadComplexFromAddr(V, false));
     else if (CodeGenFunction::hasAggregateLLVMType(RetTy))