diff options
Diffstat (limited to 'llvm/lib/Target/Sparc')
| -rw-r--r-- | llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp | 30 | ||||
| -rw-r--r-- | llvm/lib/Target/Sparc/Sparc.burg.in | 4 | ||||
| -rw-r--r-- | llvm/lib/Target/Sparc/SparcInstrSelection.cpp | 218 | ||||
| -rw-r--r-- | llvm/lib/Target/Sparc/SparcInternals.h | 4 | 
4 files changed, 179 insertions, 77 deletions
| diff --git a/llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp b/llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp index be55e3b0a20..532a178a33b 100644 --- a/llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp +++ b/llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp @@ -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 { @@ -93,6 +95,34 @@ void InsertPrologEpilogCode::InsertPrologCode(MachineFunction &MF)      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());  } diff --git a/llvm/lib/Target/Sparc/Sparc.burg.in b/llvm/lib/Target/Sparc/Sparc.burg.in index 6d28d8ad06c..516a1fcb4bd 100644 --- a/llvm/lib/Target/Sparc/Sparc.burg.in +++ b/llvm/lib/Target/Sparc/Sparc.burg.in @@ -87,7 +87,8 @@ Xdefine PANIC		printf  %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:	Call			=   61 (20);	/* just ignore the operands! */  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. diff --git a/llvm/lib/Target/Sparc/SparcInstrSelection.cpp b/llvm/lib/Target/Sparc/SparcInstrSelection.cpp index 61a804513e2..709c338fd35 100644 --- a/llvm/lib/Target/Sparc/SparcInstrSelection.cpp +++ b/llvm/lib/Target/Sparc/SparcInstrSelection.cpp @@ -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 @@ AllUsesAreBranches(const Instruction* setccI)    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 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,                  //           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); +        // Check if this is an intrinsic function that needs a special code +        // sequence (e.g., va_start).  Indirect calls cannot be special. +        //  +        bool specialIntrinsic = false; +        LLVMIntrinsic::ID iid; +        if (calledFunc && (iid=(LLVMIntrinsic::ID)calledFunc->getIntrinsicID())) +          specialIntrinsic = CodeGenIntrinsic(iid, *callInstr, target, mvec); -        // 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 not, generate the normal call sequence for the function. +        // This can also handle any intrinsics that are just function calls.          //  -        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); +        if (! specialIntrinsic) +          { +            // 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); +            const FunctionType* funcType = +              cast<FunctionType>(cast<PointerType>(callee->getType()) +                                 ->getElementType()); +            bool isVarArgs = funcType->isVarArg(); +            bool noPrototype = isVarArgs && funcType->getNumParams() == 0; -        assert(callInstr->getOperand(0) == callee -               && "This is assumed in the loop below!"); -         -        for (unsigned i=1, N=callInstr->getNumOperands(); i < N; ++i) -          { -            Value* argVal = callInstr->getOperand(i); -            Instruction* intArgReg = NULL; +            // 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); +            // 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); +            // 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 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,        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 diff --git a/llvm/lib/Target/Sparc/SparcInternals.h b/llvm/lib/Target/Sparc/SparcInternals.h index ec04d3b8d2c..f49f6158333 100644 --- a/llvm/lib/Target/Sparc/SparcInternals.h +++ b/llvm/lib/Target/Sparc/SparcInternals.h @@ -374,8 +374,8 @@ public:    // 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 | 

