This patch causes us to compile functions like:

p1 (f2, l)
float f2; short l;  {
  printf("%d\n", l);
}

into:

define i32 %p1(double %f2, i32 %l) {

instead of:

define i32 %p1(float %f2, i16 %l) {

due to K&R promotion rules. This fixes a miscompilation of SingleSource/UnitTests/2007-01-04-KNR-Args.c on PowerPC at -O0.

-Chris


Index: llvm-convert.cpp
===================================================================
--- llvm-convert.cpp    (revision 122009)
+++ llvm-convert.cpp    (working copy)
@@ -211,12 +211,15 @@ namespace {
       if (ArgVal->getType() != LLVMTy) {
         // If this is just a mismatch between integer types, this could be due
         // to K&R prototypes, where the forward proto defines the arg as int 
and
-        // the actual impls is a short or char.
-        assert(ArgVal->getType()->isIntegral() && LLVMTy->isIntegral() &&
+        // the actual impls is a short or char.  Likewise for double -> float.
+        assert(ArgVal->getType()->isIntegral() == LLVMTy->isIntegral() &&
+               (ArgVal->getType() == Type::Int32Ty ||
+                ArgVal->getType() == Type::DoubleTy) &&
                "Lowerings don't match?");
-        bool isSigned = type == 0 ? true : !TYPE_UNSIGNED(type);
-        ArgVal = CastInst::createIntegerCast(ArgVal, LLVMTy, isSigned,
-                                             NameStack.back(), CurBB);
+        if (ArgVal->getType() == Type::Int32Ty)
+          ArgVal = new TruncInst(ArgVal, LLVMTy, NameStack.back(), CurBB);
+        else
+          ArgVal = new FPTruncInst(ArgVal, LLVMTy, NameStack.back(), CurBB);
       }
       assert(!LocStack.empty());
       Value *Loc = LocStack.back();
Index: llvm-types.cpp
===================================================================
--- llvm-types.cpp      (revision 122009)
+++ llvm-types.cpp      (working copy)
@@ -474,10 +474,11 @@ namespace {
     const Type *&RetTy;
     std::vector<const Type*> &ArgTypes;
     unsigned &CallingConv;
+    bool KNRPromotion;
   public:
     FunctionTypeConversion(const Type *&retty, std::vector<const Type*> &AT,
-                           unsigned &CC)
-      : RetTy(retty), ArgTypes(AT), CallingConv(CC) {
+                           unsigned &CC, bool KNR)
+      : RetTy(retty), ArgTypes(AT), CallingConv(CC), KNRPromotion(KNR) {
       CallingConv = CallingConv::C;
     }
     
@@ -512,6 +513,16 @@ namespace {
     }
     
     void HandleScalarArgument(const llvm::Type *LLVMTy, tree type) {
+      if (KNRPromotion) {
+        if (LLVMTy == Type::FloatTy) {
+          ArgTypes.push_back(Type::DoubleTy);
+          return;
+        } else if (LLVMTy == Type::Int16Ty || LLVMTy == Type::Int8Ty ||
+                   LLVMTy == Type::BoolTy) {
+          ArgTypes.push_back(Type::Int32Ty);
+          return;
+        }
+      }        
       ArgTypes.push_back(LLVMTy);
     }
   };
@@ -528,7 +539,7 @@ ConvertArgListToFnType(tree ReturnType, 
   std::vector<const Type*> ArgTys;
   const Type *RetTy;
   
-  FunctionTypeConversion Client(RetTy, ArgTys, CallingConv);
+  FunctionTypeConversion Client(RetTy, ArgTys, CallingConv, true /*K&R*/);
   TheLLVMABI<FunctionTypeConversion> ABIConverter(Client);
   
   ABIConverter.HandleReturnType(ReturnType);
@@ -542,7 +553,7 @@ const FunctionType *TypeConverter::Conve
   const Type *RetTy = 0;
   std::vector<const Type*> ArgTypes;
   bool isVarArg = false;
-  FunctionTypeConversion Client(RetTy, ArgTypes, CallingConv);
+  FunctionTypeConversion Client(RetTy, ArgTypes, CallingConv, true /*not 
K&R*/);
   TheLLVMABI<FunctionTypeConversion> ABIConverter(Client);
   
   ABIConverter.HandleReturnType(TREE_TYPE(type));
_______________________________________________
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

Reply via email to