Numerous bug fixes:
-- correct sign extensions for integer casts and for shift-by-constant
   instructions generated for integer multiply
-- passing FP arguments to functions with more than 6 arguments
-- passing FP arguments to varargs functions
-- passing FP arguments to functions with no prototypes
-- incorrect stack frame size when padding a section
-- folding getelementptr operations with mixed array and struct indexes
-- use uint64_t instead of uint for constant offsets in mem operands
-- incorrect coloring for CC registers (both int and FP): interferences
   were being completely ignored for int CC and were considered but no
   spills were marked for fp CC!

Also some code improvements:
-- better interface to generating machine instr for common cases
   (many places still need to be updated to use this interface)
-- annotations on MachineInstr to communicate information from
   one codegen phase to another (now used to pass information about
   CALL/JMPLCALL operands from selection to register allocation)
-- all sizes and offests in class TargetData are uint64_t instead of uint


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2640 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/SparcV9/SparcV9InstrInfo.cpp b/lib/Target/SparcV9/SparcV9InstrInfo.cpp
index fd18841..5fbced0 100644
--- a/lib/Target/SparcV9/SparcV9InstrInfo.cpp
+++ b/lib/Target/SparcV9/SparcV9InstrInfo.cpp
@@ -16,7 +16,10 @@
 #include "llvm/CodeGen/InstrSelection.h"
 #include "llvm/CodeGen/InstrSelectionSupport.h"
 #include "llvm/CodeGen/MachineCodeForMethod.h"
+#include "llvm/CodeGen/MachineCodeForInstruction.h"
 #include "llvm/Function.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/Instruction.h"
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
 
@@ -24,56 +27,87 @@
 //************************ Internal Functions ******************************/
 
 
-static inline MachineInstr*
-CreateIntSetInstruction(int64_t C, Value* dest,
-                        std::vector<TmpInstruction*>& tempVec)
+static inline void
+CreateIntSetInstruction(const TargetMachine& target, Function* F,
+                        int64_t C, Instruction* dest,
+                        std::vector<MachineInstr*>& mvec,
+                        MachineCodeForInstruction& mcfi)
 {
-  MachineInstr* minstr;
+  assert(dest->getType()->isSigned() && "Use CreateUIntSetInstruction()");
+  
+  MachineInstr* M;
   uint64_t absC = (C >= 0)? C : -C;
   if (absC > (unsigned int) ~0)
     { // C does not fit in 32 bits
       TmpInstruction* tmpReg = new TmpInstruction(Type::IntTy);
-      tempVec.push_back(tmpReg);
+      mcfi.addTemp(tmpReg);
       
-      minstr = new MachineInstr(SETX);
-      minstr->SetMachineOperandConst(0, MachineOperand::MO_SignExtendedImmed, C);
-      minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
-                                   /*isdef*/ true);
-      minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
+      M = new MachineInstr(SETX);
+      M->SetMachineOperandConst(0,MachineOperand::MO_SignExtendedImmed,C);
+      M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
+                                 /*isdef*/ true);
+      M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
+      mvec.push_back(M);
     }
   else
     {
-      minstr = new MachineInstr(SETSW);
-      minstr->SetMachineOperandConst(0,MachineOperand::MO_SignExtendedImmed,C);
-      minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,dest);
+      M = Create2OperandInstr_SImmed(SETSW, C, dest);
+      mvec.push_back(M);
     }
-  
-  return minstr;
 }
 
-static inline MachineInstr*
-CreateUIntSetInstruction(uint64_t C, Value* dest,
-                         std::vector<TmpInstruction*>& tempVec)
+static inline void
+CreateUIntSetInstruction(const TargetMachine& target, Function* F,
+                         uint64_t C, Instruction* dest,
+                         std::vector<MachineInstr*>& mvec,
+                         MachineCodeForInstruction& mcfi)
 {
-  MachineInstr* minstr;
+  assert(! dest->getType()->isSigned() && "Use CreateIntSetInstruction()");
+  unsigned destSize = target.DataLayout.getTypeSize(dest->getType());
+  MachineInstr* M;
+  
   if (C > (unsigned int) ~0)
     { // C does not fit in 32 bits
       assert(dest->getType() == Type::ULongTy && "Sign extension problems");
       TmpInstruction *tmpReg = new TmpInstruction(Type::IntTy);
-      tempVec.push_back(tmpReg);
+      mcfi.addTemp(tmpReg);
       
-      minstr = new MachineInstr(SETX);
-      minstr->SetMachineOperandConst(0,MachineOperand::MO_SignExtendedImmed,C);
-      minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,
-                                   tmpReg, /*isdef*/ true);
-      minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
+      M = new MachineInstr(SETX);
+      M->SetMachineOperandConst(0, MachineOperand::MO_UnextendedImmed, C);
+      M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
+                              /*isdef*/ true);
+      M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
+      mvec.push_back(M);
     }
-  else if (dest->getType() == Type::ULongTy)
+  else
     {
-      minstr = new MachineInstr(SETUW);
-      minstr->SetMachineOperandConst(0, MachineOperand::MO_UnextendedImmed, C);
-      minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,dest);
+      // If the destination is smaller than the standard integer reg. size,
+      // we have to extend the sign-bit into upper bits of dest, so we
+      // need to put the result of the SETUW into a temporary.
+      // 
+      Value* setuwDest = dest;
+      if (destSize < target.DataLayout.getIntegerRegize())
+        {
+          setuwDest = new TmpInstruction(dest, NULL, "setTmp");
+          mcfi.addTemp(setuwDest);
+        }
+      
+      M = Create2OperandInstr_UImmed(SETUW, C, setuwDest);
+      mvec.push_back(M);
+      
+      if (setuwDest != dest)
+        { // extend the sign-bit of the result into all upper bits of dest
+          assert(8*destSize <= 32 &&
+                 "Unexpected type size > 4 and < IntRegSize?");
+          target.getInstrInfo().
+            CreateSignExtensionInstructions(target, F,
+                                            setuwDest, 8*destSize, dest,
+                                            mvec, mcfi);
+        }
     }
+  
+#define USE_DIRECT_SIGN_EXTENSION_INSTRS
+#ifndef USE_DIRECT_SIGN_EXTENSION_INSTRS
   else
     { // cast to signed type of the right length and use signed op (SETSW)
       // to get correct sign extension
@@ -103,8 +137,7 @@
           break;
         }
     }
-  
-  return minstr;
+#endif USE_DIRECT_SIGN_EXTENSION_INSTRS
 }
 
 //************************* External Classes *******************************/
@@ -131,17 +164,18 @@
 // Create an instruction sequence to put the constant `val' into
 // the virtual register `dest'.  `val' may be a Constant or a
 // GlobalValue, viz., the constant address of a global variable or function.
-// The generated instructions are returned in `minstrVec'.
-// Any temp. registers (TmpInstruction) created are returned in `tempVec'.
+// The generated instructions are returned in `mvec'.
+// Any temp. registers (TmpInstruction) created are recorded in mcfi.
+// Any stack space required is allocated via MachineCodeForMethod.
 // 
 void
-UltraSparcInstrInfo::CreateCodeToLoadConst(Function *F, Value* val,
+UltraSparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target,
+                                           Function* F,
+                                           Value* val,
                                            Instruction* dest,
-                                           std::vector<MachineInstr*>&minstrVec,
-                                    std::vector<TmpInstruction*>& tempVec) const
+                                           std::vector<MachineInstr*>& mvec,
+                                       MachineCodeForInstruction& mcfi) const
 {
-  MachineInstr* minstr;
-  
   assert(isa<Constant>(val) || isa<GlobalValue>(val) &&
          "I only know about constant values and global addresses");
   
@@ -153,19 +187,18 @@
   
   if (valType->isIntegral() || valType == Type::BoolTy)
     {
-      if (ConstantUInt* uval = dyn_cast<ConstantUInt>(val))
+      if (! val->getType()->isSigned())
         {
-          uint64_t C = uval->getValue();
-          minstr = CreateUIntSetInstruction(C, dest, tempVec);
+          uint64_t C = cast<ConstantUInt>(val)->getValue();
+          CreateUIntSetInstruction(target, F, C, dest, mvec, mcfi);
         }
       else
         {
           bool isValidConstant;
           int64_t C = GetConstantValueAsSignedInt(val, isValidConstant);
           assert(isValidConstant && "Unrecognized constant");
-          minstr = CreateIntSetInstruction(C, dest, tempVec);
+          CreateIntSetInstruction(target, F, C, dest, mvec, mcfi);
         }
-      minstrVec.push_back(minstr);
     }
   else
     {
@@ -180,42 +213,35 @@
       
       TmpInstruction* tmpReg =
         new TmpInstruction(PointerType::get(val->getType()), val);
-      tempVec.push_back(tmpReg);
+      mcfi.addTemp(tmpReg);
       
       if (isa<Constant>(val))
         {
           // Create another TmpInstruction for the hidden integer register
           TmpInstruction* addrReg =
             new TmpInstruction(PointerType::get(val->getType()), val);
-          tempVec.push_back(addrReg);
+          mcfi.addTemp(addrReg);
           addrVal = addrReg;
         }
       else
         addrVal = dest;
       
-      minstr = new MachineInstr(SETX);
-      minstr->SetMachineOperandVal(0, MachineOperand::MO_PCRelativeDisp, val);
-      minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,tmpReg,
-                                   /*isdef*/ true);
-      minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
-                                   addrVal);
-      minstrVec.push_back(minstr);
+      MachineInstr* M = new MachineInstr(SETX);
+      M->SetMachineOperandVal(0, MachineOperand::MO_PCRelativeDisp, val);
+      M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
+                              /*isdef*/ true);
+      M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, addrVal);
+      mvec.push_back(M);
       
       if (isa<Constant>(val))
         {
           // Make sure constant is emitted to constant pool in assembly code.
-          MachineCodeForMethod& mcinfo = MachineCodeForMethod::get(F);
-          mcinfo.addToConstantPool(cast<Constant>(val));
+          MachineCodeForMethod::get(F).addToConstantPool(cast<Constant>(val));
           
           // Generate the load instruction
-          minstr = new MachineInstr(ChooseLoadInstruction(val->getType()));
-          minstr->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
-                                       addrVal);
-          minstr->SetMachineOperandConst(1,MachineOperand::MO_SignExtendedImmed,
-                                       zeroOffset);
-          minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
-                                       dest);
-          minstrVec.push_back(minstr);
+          M = Create3OperandInstr_SImmed(ChooseLoadInstruction(val->getType()),
+                                         addrVal, zeroOffset, dest);
+          mvec.push_back(M);
         }
     }
 }
@@ -224,24 +250,24 @@
 // Create an instruction sequence to copy an integer value `val'
 // to a floating point value `dest' by copying to memory and back.
 // val must be an integral type.  dest must be a Float or Double.
-// The generated instructions are returned in `minstrVec'.
-// Any temp. registers (TmpInstruction) created are returned in `tempVec'.
+// The generated instructions are returned in `mvec'.
+// Any temp. registers (TmpInstruction) created are recorded in mcfi.
+// Any stack space required is allocated via MachineCodeForMethod.
 // 
 void
-UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(Function *F,
-                                         Value* val,
-                                         Instruction* dest,
-                                         std::vector<MachineInstr*>& minstrVec,
-                                         std::vector<TmpInstruction*>& tempVec,
-                                         TargetMachine& target) const
+UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target,
+                                        Function* F,
+                                        Value* val,
+                                        Instruction* dest,
+                                        std::vector<MachineInstr*>& mvec,
+                                        MachineCodeForInstruction& mcfi) const
 {
   assert((val->getType()->isIntegral() || isa<PointerType>(val->getType()))
          && "Source type must be integral");
   assert(dest->getType()->isFloatingPoint()
          && "Dest type must be float/double");
   
-  MachineCodeForMethod& mcinfo = MachineCodeForMethod::get(F);
-  int offset = mcinfo.allocateLocalVar(target, val); 
+  int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val); 
   
   // Store instruction stores `val' to [%fp+offset].
   // The store and load opCodes are based on the value being copied, and
@@ -254,8 +280,8 @@
   MachineInstr* store = new MachineInstr(ChooseStoreInstruction(tmpType));
   store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
   store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
-  store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed, offset);
-  minstrVec.push_back(store);
+  store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
+  mvec.push_back(store);
 
   // Load instruction loads [%fp+offset] to `dest'.
   // 
@@ -263,29 +289,30 @@
   load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
   load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
   load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
-  minstrVec.push_back(load);
+  mvec.push_back(load);
 }
 
 
 // Similarly, create an instruction sequence to copy an FP value
 // `val' to an integer value `dest' by copying to memory and back.
-// See the previous function for information about return values.
+// The generated instructions are returned in `mvec'.
+// Any temp. registers (TmpInstruction) created are recorded in mcfi.
+// Any stack space required is allocated via MachineCodeForMethod.
 // 
 void
-UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(Function *F,
+UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target,
+                                        Function* F,
                                         Value* val,
                                         Instruction* dest,
-                                        std::vector<MachineInstr*>& minstrVec,
-                                        std::vector<TmpInstruction*>& tempVec,
-                                        TargetMachine& target) const
+                                        std::vector<MachineInstr*>& mvec,
+                                        MachineCodeForInstruction& mcfi) const
 {
   assert(val->getType()->isFloatingPoint()
          && "Source type must be float/double");
   assert((dest->getType()->isIntegral() || isa<PointerType>(dest->getType()))
          && "Dest type must be integral");
   
-  MachineCodeForMethod& mcinfo = MachineCodeForMethod::get(F);
-  int offset = mcinfo.allocateLocalVar(target, val); 
+  int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val); 
   
   // Store instruction stores `val' to [%fp+offset].
   // The store and load opCodes are based on the value being copied, and
@@ -298,13 +325,113 @@
   store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
   store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
   store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
-  minstrVec.push_back(store);
+  mvec.push_back(store);
   
   // Load instruction loads [%fp+offset] to `dest'.
   // 
   MachineInstr* load = new MachineInstr(ChooseLoadInstruction(tmpType));
   load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
-  load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed, offset);
+  load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
   load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
-  minstrVec.push_back(load);
+  mvec.push_back(load);
+}
+
+
+// Create instruction(s) to copy src to dest, for arbitrary types
+// The generated instructions are returned in `mvec'.
+// Any temp. registers (TmpInstruction) created are recorded in mcfi.
+// Any stack space required is allocated via MachineCodeForMethod.
+// 
+void
+UltraSparcInstrInfo::CreateCopyInstructionsByType(const TargetMachine& target,
+                                                  Function *F,
+                                                  Value* src,
+                                                  Instruction* dest,
+                                                  vector<MachineInstr*>& mvec,
+                                          MachineCodeForInstruction& mcfi) const
+{
+  bool loadConstantToReg = false;
+  
+  const Type* resultType = dest->getType();
+  
+  MachineOpCode opCode = ChooseAddInstructionByType(resultType);
+  if (opCode == INVALID_OPCODE)
+    {
+      assert(0 && "Unsupported result type in CreateCopyInstructionsByType()");
+      return;
+    }
+  
+  // if `src' is a constant that doesn't fit in the immed field or if it is
+  // a global variable (i.e., a constant address), generate a load
+  // instruction instead of an add
+  // 
+  if (isa<Constant>(src))
+    {
+      unsigned int machineRegNum;
+      int64_t immedValue;
+      MachineOperand::MachineOperandType opType =
+        ChooseRegOrImmed(src, opCode, target, /*canUseImmed*/ true,
+                         machineRegNum, immedValue);
+      
+      if (opType == MachineOperand::MO_VirtualRegister)
+        loadConstantToReg = true;
+    }
+  else if (isa<GlobalValue>(src))
+    loadConstantToReg = true;
+  
+  if (loadConstantToReg)
+    { // `src' is constant and cannot fit in immed field for the ADD
+      // Insert instructions to "load" the constant into a register
+      target.getInstrInfo().CreateCodeToLoadConst(target, F, src, dest,
+                                                  mvec, mcfi);
+    }
+  else
+    { // Create an add-with-0 instruction of the appropriate type.
+      // Make `src' the second operand, in case it is a constant
+      // Use (unsigned long) 0 for a NULL pointer value.
+      // 
+      const Type* zeroValueType =
+        isa<PointerType>(resultType) ? Type::ULongTy : resultType;
+      MachineInstr* minstr =
+        Create3OperandInstr(opCode, Constant::getNullValue(zeroValueType),
+                            src, dest);
+      mvec.push_back(minstr);
+    }
+}
+
+
+// Create instruction sequence to produce a sign-extended register value
+// from an arbitrary sized value (sized in bits, not bytes).
+// For SPARC v9, we sign-extend the given unsigned operand using SLL; SRA.
+// The generated instructions are returned in `mvec'.
+// Any temp. registers (TmpInstruction) created are recorded in mcfi.
+// Any stack space required is allocated via MachineCodeForMethod.
+// 
+void
+UltraSparcInstrInfo::CreateSignExtensionInstructions(
+                                        const TargetMachine& target,
+                                        Function* F,
+                                        Value* unsignedSrcVal,
+                                        unsigned int srcSizeInBits,
+                                        Value* dest,
+                                        vector<MachineInstr*>& mvec,
+                                        MachineCodeForInstruction& mcfi) const
+{
+  MachineInstr* M;
+  
+  assert(srcSizeInBits > 0 && srcSizeInBits <= 32
+     && "Hmmm... srcSizeInBits > 32 unexpected but could be handled here.");
+  
+  if (srcSizeInBits < 32)
+    { // SLL is needed since operand size is < 32 bits.
+      TmpInstruction *tmpI = new TmpInstruction(dest->getType(),
+                                                unsignedSrcVal, dest,"make32");
+      mcfi.addTemp(tmpI);
+      M = Create3OperandInstr_UImmed(SLL,unsignedSrcVal,32-srcSizeInBits,tmpI);
+      mvec.push_back(M);
+      unsignedSrcVal = tmpI;
+    }
+  
+  M = Create3OperandInstr_UImmed(SRA, unsignedSrcVal, 32-srcSizeInBits, dest);
+  mvec.push_back(M);
 }