+// 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;
+ }
+}
+