[llvm-commits] CVS: llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp Sparc.burg.in SparcInstrSelection.cpp SparcInternals.h

Vikram Adve vadve at cs.uiuc.edu
Sun May 25 11:00:01 PDT 2003


Changes in directory llvm/lib/Target/Sparc:

PrologEpilogCodeInserter.cpp updated: 1.24 -> 1.25
Sparc.burg.in updated: 1.4 -> 1.5
SparcInstrSelection.cpp updated: 1.91 -> 1.92
SparcInternals.h updated: 1.83 -> 1.84

---
Log message:

Add support for compiling varargs functions.


---
Diffs of the changes:

Index: llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp
diff -u llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp:1.24 llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp:1.25
--- llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp:1.24	Tue May 20 15:32:23 2003
+++ llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp	Sun May 25 10:59:47 2003
@@ -17,6 +17,8 @@
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/Pass.h"
 #include "llvm/Function.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Intrinsics.h"
 
 namespace {
   struct InsertPrologEpilogCode : public MachineFunctionPass {
@@ -91,6 +93,34 @@
     // Now generate the SAVE using the value in register %g1
     M = BuildMI(V9::SAVE, 3).addMReg(SP).addMReg(uregNum).addMReg(SP,MOTy::Def);
     mvec.push_back(M);
+  }
+
+  // For varargs function bodies, insert instructions to copy incoming
+  // register arguments for the ... list to the stack.
+  // The first K=6 arguments are always received via int arg regs
+  // (%i0 ... %i5 if K=6) .
+  // By copying the varargs arguments to the stack, va_arg() then can
+  // simply assume that all vararg arguments are in an array on the stack. 
+  // 
+  if (MF.getFunction()->getFunctionType()->isVarArg()) {
+    int numFixedArgs    = MF.getFunction()->getFunctionType()->getNumParams();
+    int numArgRegs      = TM.getRegInfo().getNumOfIntArgRegs();
+    if (numFixedArgs < numArgRegs) {
+      bool ignore;
+      int firstArgReg   = TM.getRegInfo().getUnifiedRegNum(
+                             TM.getRegInfo().getRegClassIDOfType(Type::IntTy),
+                             SparcIntRegClass::i0);
+      int fpReg         = TM.getFrameInfo().getIncomingArgBaseRegNum();
+      int argSize       = TM.getFrameInfo().getSizeOfEachArgOnStack();
+      int firstArgOffset=TM.getFrameInfo().getFirstIncomingArgOffset(MF,ignore);
+      int nextArgOffset = firstArgOffset + numFixedArgs * argSize;
+
+      for (int i=numFixedArgs; i < numArgRegs; ++i) {
+        mvec.push_back(BuildMI(V9::STX, 3).addMReg(firstArgReg+i).
+                       addMReg(fpReg).addSImm(nextArgOffset));
+        nextArgOffset += argSize;
+      }
+    }
   }
 
   MF.front().insert(MF.front().begin(), mvec.begin(), mvec.end());


Index: llvm/lib/Target/Sparc/Sparc.burg.in
diff -u llvm/lib/Target/Sparc/Sparc.burg.in:1.4 llvm/lib/Target/Sparc/Sparc.burg.in:1.5
--- llvm/lib/Target/Sparc/Sparc.burg.in:1.4	Sat Aug 24 15:58:04 2002
+++ llvm/lib/Target/Sparc/Sparc.burg.in	Sun May 25 10:59:47 2003
@@ -87,7 +87,8 @@
 %term Call=CallOPCODE
 %term Shl=ShlOPCODE
 %term Shr=ShrOPCODE
-		/* 30...46 are unused */
+%term VaArg=VarArgOPCODE
+		/* 32...46 are unused */
     /*
      * The foll. values should match the constants in InstrForest.h
      */
@@ -256,6 +257,7 @@
 reg:	Shl(reg,reg)		=   62 (20);	/* 1 for issue restrictions */
 reg:	Shr(reg,reg)		=   63 (20);	/* 1 for issue restrictions */
 reg:	Phi(reg,reg)		=   64 (0);
+reg:	VaArg(reg)		=   65 (40);	/* load from stack then incr */
 
 	/*
 	 * Finally, leaf nodes of expression trees.


Index: llvm/lib/Target/Sparc/SparcInstrSelection.cpp
diff -u llvm/lib/Target/Sparc/SparcInstrSelection.cpp:1.91 llvm/lib/Target/Sparc/SparcInstrSelection.cpp:1.92
--- llvm/lib/Target/Sparc/SparcInstrSelection.cpp:1.91	Wed May 21 13:48:06 2003
+++ llvm/lib/Target/Sparc/SparcInstrSelection.cpp	Sun May 25 10:59:47 2003
@@ -22,6 +22,7 @@
 #include "llvm/Function.h"
 #include "llvm/Constants.h"
 #include "llvm/ConstantHandling.h"
+#include "llvm/Intrinsics.h"
 #include "Support/MathExtras.h"
 #include <math.h>
 
@@ -1298,6 +1299,46 @@
   return true;
 }
 
+// Generate code for any intrinsic that needs a special code sequence
+// instead of a regular call.  If not that kind of intrinsic, do nothing.
+// Returns true if code was generated, otherwise false.
+// 
+bool CodeGenIntrinsic(LLVMIntrinsic::ID iid, CallInst &callInstr,
+                      TargetMachine &target,
+                      std::vector<MachineInstr*>& mvec)
+{
+  switch (iid) {
+  case LLVMIntrinsic::va_start: {
+    // Get the address of the first vararg value on stack and copy it to
+    // the argument of va_start(va_list* ap).
+    bool ignore;
+    Function* func = cast<Function>(callInstr.getParent()->getParent());
+    int numFixedArgs   = func->getFunctionType()->getNumParams();
+    int fpReg          = target.getFrameInfo().getIncomingArgBaseRegNum();
+    int argSize        = target.getFrameInfo().getSizeOfEachArgOnStack();
+    int firstVarArgOff = numFixedArgs * argSize + target.getFrameInfo().
+      getFirstIncomingArgOffset(MachineFunction::get(func), ignore);
+    mvec.push_back(BuildMI(V9::ADD, 3).addMReg(fpReg).addSImm(firstVarArgOff).
+                   addReg(callInstr.getOperand(1)));
+    return true;
+  }
+
+  case LLVMIntrinsic::va_end:
+    return true;                        // no-op on Sparc
+
+  case LLVMIntrinsic::va_copy:
+    // Simple copy of current va_list (arg2) to new va_list (arg1)
+    mvec.push_back(BuildMI(V9::OR, 3).
+                   addMReg(target.getRegInfo().getZeroRegNum()).
+                   addReg(callInstr.getOperand(2)).
+                   addReg(callInstr.getOperand(1)));
+    return true;
+
+  default:
+    return false;
+  }
+}
+
 //******************* Externally Visible Functions *************************/
 
 //------------------------------------------------------------------------ 
@@ -2101,96 +2142,112 @@
                 // 
         CallInst *callInstr = cast<CallInst>(subtreeRoot->getInstruction());
         Value *callee = callInstr->getCalledValue();
+        Function* calledFunc = dyn_cast<Function>(callee);
 
-        // Create hidden virtual register for return address with type void*
-        TmpInstruction* retAddrReg =
-          new TmpInstruction(PointerType::get(Type::VoidTy), callInstr);
-        MachineCodeForInstruction::get(callInstr).addTemp(retAddrReg);
-
-        // Generate the machine instruction and its operands.
-        // Use CALL for direct function calls; this optimistically assumes
-        // the PC-relative address fits in the CALL address field (22 bits).
-        // Use JMPL for indirect calls.
+        // Check if this is an intrinsic function that needs a special code
+        // sequence (e.g., va_start).  Indirect calls cannot be special.
         // 
-        if (isa<Function>(callee))      // direct function call
-          M = BuildMI(V9::CALL, 1).addPCDisp(callee);
-        else                            // indirect function call
-          M = BuildMI(V9::JMPLCALL, 3).addReg(callee).addSImm((int64_t)0)
-            .addRegDef(retAddrReg);
-        mvec.push_back(M);
+        bool specialIntrinsic = false;
+        LLVMIntrinsic::ID iid;
+        if (calledFunc && (iid=(LLVMIntrinsic::ID)calledFunc->getIntrinsicID()))
+          specialIntrinsic = CodeGenIntrinsic(iid, *callInstr, target, mvec);
 
-        const FunctionType* funcType =
-          cast<FunctionType>(cast<PointerType>(callee->getType())
-                             ->getElementType());
-        bool isVarArgs = funcType->isVarArg();
-        bool noPrototype = isVarArgs && funcType->getNumParams() == 0;
-        
-        // Use a descriptor to pass information about call arguments
-        // to the register allocator.  This descriptor will be "owned"
-        // and freed automatically when the MachineCodeForInstruction
-        // object for the callInstr goes away.
-        CallArgsDescriptor* argDesc = new CallArgsDescriptor(callInstr,
-                                         retAddrReg, isVarArgs, noPrototype);
-        
-        assert(callInstr->getOperand(0) == callee
-               && "This is assumed in the loop below!");
-        
-        for (unsigned i=1, N=callInstr->getNumOperands(); i < N; ++i)
+        // If not, generate the normal call sequence for the function.
+        // This can also handle any intrinsics that are just function calls.
+        // 
+        if (! specialIntrinsic)
           {
-            Value* argVal = callInstr->getOperand(i);
-            Instruction* intArgReg = NULL;
+            // Create hidden virtual register for return address with type void*
+            TmpInstruction* retAddrReg =
+              new TmpInstruction(PointerType::get(Type::VoidTy), callInstr);
+            MachineCodeForInstruction::get(callInstr).addTemp(retAddrReg);
+
+            // Generate the machine instruction and its operands.
+            // Use CALL for direct function calls; this optimistically assumes
+            // the PC-relative address fits in the CALL address field (22 bits).
+            // Use JMPL for indirect calls.
+            // 
+            if (calledFunc)             // direct function call
+              M = BuildMI(V9::CALL, 1).addPCDisp(callee);
+            else                        // indirect function call
+              M = BuildMI(V9::JMPLCALL, 3).addReg(callee).addSImm((int64_t)0)
+                .addRegDef(retAddrReg);
+            mvec.push_back(M);
+
+            const FunctionType* funcType =
+              cast<FunctionType>(cast<PointerType>(callee->getType())
+                                 ->getElementType());
+            bool isVarArgs = funcType->isVarArg();
+            bool noPrototype = isVarArgs && funcType->getNumParams() == 0;
+        
+            // Use a descriptor to pass information about call arguments
+            // to the register allocator.  This descriptor will be "owned"
+            // and freed automatically when the MachineCodeForInstruction
+            // object for the callInstr goes away.
+            CallArgsDescriptor* argDesc = new CallArgsDescriptor(callInstr,
+                                             retAddrReg, isVarArgs,noPrototype);
             
-            // Check for FP arguments to varargs functions.
-            // Any such argument in the first $K$ args must be passed in an
-            // integer register, where K = #integer argument registers.
-            if (isVarArgs && argVal->getType()->isFloatingPoint())
+            assert(callInstr->getOperand(0) == callee
+                   && "This is assumed in the loop below!");
+            
+            for (unsigned i=1, N=callInstr->getNumOperands(); i < N; ++i)
               {
-                // If it is a function with no prototype, pass value
-                // as an FP value as well as a varargs value
-                if (noPrototype)
-                  argDesc->getArgInfo(i-1).setUseFPArgReg();
-                
-                // If this arg. is in the first $K$ regs, add a copy
-                // float-to-int instruction to pass the value as an integer.
-                if (i <= target.getRegInfo().GetNumOfIntArgRegs())
+                Value* argVal = callInstr->getOperand(i);
+                Instruction* intArgReg = NULL;
+            
+                // Check for FP arguments to varargs functions.
+                // Any such argument in the first $K$ args must be passed in an
+                // integer register, where K = #integer argument registers.
+                if (isVarArgs && argVal->getType()->isFloatingPoint())
                   {
-                    MachineCodeForInstruction &destMCFI = 
-                      MachineCodeForInstruction::get(callInstr);   
-                    intArgReg = new TmpInstruction(Type::IntTy, argVal);
-                    destMCFI.addTemp(intArgReg);
+                    // If it is a function with no prototype, pass value
+                    // as an FP value as well as a varargs value
+                    if (noPrototype)
+                      argDesc->getArgInfo(i-1).setUseFPArgReg();
+                
+                    // If this arg. is in the first $K$ regs, add a copy
+                    // float-to-int instruction to pass the value as an integer.
+                    if (i <= target.getRegInfo().getNumOfIntArgRegs())
+                      {
+                        MachineCodeForInstruction &destMCFI = 
+                          MachineCodeForInstruction::get(callInstr);   
+                        intArgReg = new TmpInstruction(Type::IntTy, argVal);
+                        destMCFI.addTemp(intArgReg);
                     
-                    std::vector<MachineInstr*> copyMvec;
-                    target.getInstrInfo().CreateCodeToCopyFloatToInt(target,
-                                           callInstr->getParent()->getParent(),
-                                           argVal, (TmpInstruction*) intArgReg,
-                                           copyMvec, destMCFI);
-                    mvec.insert(mvec.begin(),copyMvec.begin(),copyMvec.end());
+                        std::vector<MachineInstr*> copyMvec;
+                        target.getInstrInfo().CreateCodeToCopyFloatToInt(target,
+                                         callInstr->getParent()->getParent(),
+                                         argVal, (TmpInstruction*) intArgReg,
+                                         copyMvec, destMCFI);
+                        mvec.insert(mvec.begin(),copyMvec.begin(),copyMvec.end());
                     
-                    argDesc->getArgInfo(i-1).setUseIntArgReg();
-                    argDesc->getArgInfo(i-1).setArgCopy(intArgReg);
+                        argDesc->getArgInfo(i-1).setUseIntArgReg();
+                        argDesc->getArgInfo(i-1).setArgCopy(intArgReg);
+                      }
+                    else
+                      // Cannot fit in first $K$ regs so pass arg on stack
+                      argDesc->getArgInfo(i-1).setUseStackSlot();
                   }
-                else
-                  // Cannot fit in first $K$ regs so pass the arg on the stack
-                  argDesc->getArgInfo(i-1).setUseStackSlot();
-              }
             
-            if (intArgReg)
-              mvec.back()->addImplicitRef(intArgReg);
+                if (intArgReg)
+                  mvec.back()->addImplicitRef(intArgReg);
             
-            mvec.back()->addImplicitRef(argVal);
-          }
+                mvec.back()->addImplicitRef(argVal);
+              }
         
-        // Add the return value as an implicit ref.  The call operands
-        // were added above.
-        if (callInstr->getType() != Type::VoidTy)
-          mvec.back()->addImplicitRef(callInstr, /*isDef*/ true);
-        
-        // For the CALL instruction, the ret. addr. reg. is also implicit
-        if (isa<Function>(callee))
-          mvec.back()->addImplicitRef(retAddrReg, /*isDef*/ true);
+            // Add the return value as an implicit ref.  The call operands
+            // were added above.
+            if (callInstr->getType() != Type::VoidTy)
+              mvec.back()->addImplicitRef(callInstr, /*isDef*/ true);
+        
+            // For the CALL instruction, the ret. addr. reg. is also implicit
+            if (isa<Function>(callee))
+              mvec.back()->addImplicitRef(retAddrReg, /*isDef*/ true);
         
-        // delay slot
-        mvec.push_back(BuildMI(V9::NOP, 0));
+            // delay slot
+            mvec.push_back(BuildMI(V9::NOP, 0));
+          }
+
         break;
       }
       
@@ -2225,6 +2282,19 @@
       case 64:	// reg:   Phi(reg,reg)
         break;                          // don't forward the value
 
+      case 65:	// reg:   VaArg(reg)
+      {
+        // Use value initialized by va_start as pointer to args on the stack.
+        // Load argument via current pointer value, then increment pointer.
+        int argSize = target.getFrameInfo().getSizeOfEachArgOnStack();
+        Instruction* vaArgI = subtreeRoot->getInstruction();
+        mvec.push_back(BuildMI(V9::LDX, 3).addReg(vaArgI->getOperand(0)).
+                       addSImm(0).addRegDef(vaArgI));
+        mvec.push_back(BuildMI(V9::ADD, 3).addReg(vaArgI->getOperand(0)).
+                       addSImm(argSize).addRegDef(vaArgI->getOperand(0)));
+        break;
+      }
+      
       case 71:	// reg:     VReg
       case 72:	// reg:     Constant
         break;                          // don't forward the value


Index: llvm/lib/Target/Sparc/SparcInternals.h
diff -u llvm/lib/Target/Sparc/SparcInternals.h:1.83 llvm/lib/Target/Sparc/SparcInternals.h:1.84
--- llvm/lib/Target/Sparc/SparcInternals.h:1.83	Fri May 23 20:08:42 2003
+++ llvm/lib/Target/Sparc/SparcInternals.h	Sun May 25 10:59:47 2003
@@ -374,8 +374,8 @@
   // Number of registers used for passing int args (usually 6: %o0 - %o5)
   // and float args (usually 32: %f0 - %f31)
   //
-  unsigned const GetNumOfIntArgRegs() const   { return NumOfIntArgRegs; }
-  unsigned const GetNumOfFloatArgRegs() const { return NumOfFloatArgRegs; }
+  unsigned const getNumOfIntArgRegs() const   { return NumOfIntArgRegs; }
+  unsigned const getNumOfFloatArgRegs() const { return NumOfFloatArgRegs; }
   
   // The following methods are used to color special live ranges (e.g.
   // function args and return values etc.) with specific hardware registers





More information about the llvm-commits mailing list