+void V8ISel::visitStoreInst(StoreInst &I) {
+ Value *SrcVal = I.getOperand (0);
+ unsigned SrcReg = getReg (SrcVal);
+ unsigned PtrReg = getReg (I.getOperand (1));
+ switch (getClassB (SrcVal->getType ())) {
+ case cByte:
+ BuildMI (BB, V8::STB, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg);
+ return;
+ case cShort:
+ BuildMI (BB, V8::STH, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg);
+ return;
+ case cInt:
+ BuildMI (BB, V8::ST, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg);
+ return;
+ case cLong:
+ BuildMI (BB, V8::ST, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg);
+ BuildMI (BB, V8::ST, 3).addReg (PtrReg).addSImm (4).addReg (SrcReg+1);
+ return;
+ case cFloat:
+ BuildMI (BB, V8::STFri, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg);
+ return;
+ case cDouble:
+ BuildMI (BB, V8::STDFri, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg);
+ return;
+ default:
+ std::cerr << "Store instruction not handled: " << I;
+ abort ();
+ return;
+ }
+}
+
+void V8ISel::visitCallInst(CallInst &I) {
+ MachineInstr *TheCall;
+ // Is it an intrinsic function call?
+ if (Function *F = I.getCalledFunction()) {
+ if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) {
+ visitIntrinsicCall(ID, I); // Special intrinsics are not handled here
+ return;
+ }
+ }
+
+ // Deal with args
+ assert (I.getNumOperands () < 8
+ && "Can't handle pushing excess call args on the stack yet");
+ static const unsigned OutgoingArgRegs[] = { V8::O0, V8::O1, V8::O2, V8::O3,
+ V8::O4, V8::O5 };
+ for (unsigned i = 1; i < 7; ++i)
+ if (i < I.getNumOperands ()) {
+ unsigned ArgReg = getReg (I.getOperand (i));
+ if (getClassB (I.getOperand (i)->getType ()) < cLong) {
+ // Schlep it over into the incoming arg register
+ BuildMI (BB, V8::ORrr, 2, OutgoingArgRegs[i - 1]).addReg (V8::G0)
+ .addReg (ArgReg);
+ } else if (getClassB (I.getOperand (i)->getType ()) == cFloat) {
+ // Single-fp args are passed in integer registers; go through
+ // memory to get them out of FP registers. (Bleh!)
+ unsigned FltAlign = TM.getTargetData().getFloatAlignment();
+ int FI = F->getFrameInfo()->CreateStackObject(4, FltAlign);
+ BuildMI (BB, V8::STFri, 3).addFrameIndex (FI).addSImm (0)
+ .addReg (ArgReg);
+ BuildMI (BB, V8::LD, 2, OutgoingArgRegs[i - 1]).addFrameIndex (FI)
+ .addSImm (0);
+ } else {
+ assert (0 && "64-bit (double, long, etc.) 'call' opnds not handled");
+ }
+ }
+
+ // Emit call instruction
+ if (Function *F = I.getCalledFunction ()) {
+ BuildMI (BB, V8::CALL, 1).addGlobalAddress (F, true);
+ } else { // Emit an indirect call...
+ unsigned Reg = getReg (I.getCalledValue ());
+ BuildMI (BB, V8::JMPLrr, 3, V8::O7).addReg (Reg).addReg (V8::G0);
+ }
+
+ // Deal w/ return value: schlep it over into the destination register
+ if (I.getType () == Type::VoidTy)
+ return;
+ unsigned DestReg = getReg (I);
+ switch (getClass (I.getType ())) {
+ case cByte:
+ case cShort:
+ case cInt:
+ BuildMI (BB, V8::ORrr, 2, DestReg).addReg(V8::G0).addReg(V8::O0);
+ break;
+ case cFloat:
+ BuildMI (BB, V8::FMOVS, 2, DestReg).addReg(V8::F0);
+ break;
+ default:
+ std::cerr << "Return type of call instruction not handled: " << I;
+ abort ();
+ }
+}
+
+void V8ISel::visitReturnInst(ReturnInst &I) {
+ if (I.getNumOperands () == 1) {
+ unsigned RetValReg = getReg (I.getOperand (0));
+ switch (getClass (I.getOperand (0)->getType ())) {
+ case cByte:
+ case cShort:
+ case cInt:
+ // Schlep it over into i0 (where it will become o0 after restore).
+ BuildMI (BB, V8::ORrr, 2, V8::I0).addReg(V8::G0).addReg(RetValReg);
+ break;
+ case cFloat:
+ BuildMI (BB, V8::FMOVS, 2, V8::F0).addReg(RetValReg);
+ break;
+ case cDouble: {
+ unsigned DoubleAlignment = TM.getTargetData().getDoubleAlignment();
+ int FI = F->getFrameInfo()->CreateStackObject(8, DoubleAlignment);
+ BuildMI (BB, V8::STDFri, 3).addFrameIndex (FI).addSImm (0)
+ .addReg (RetValReg);
+ BuildMI (BB, V8::LDDFri, 2, V8::F0).addFrameIndex (FI).addSImm (0);
+ break;
+ }
+ case cLong:
+ BuildMI (BB, V8::ORrr, 2, V8::I0).addReg(V8::G0).addReg(RetValReg);
+ BuildMI (BB, V8::ORrr, 2, V8::I1).addReg(V8::G0).addReg(RetValReg+1);
+ break;
+ default:
+ std::cerr << "Return instruction of this type not handled: " << I;
+ abort ();
+ }
+ }
+
+ // Just emit a 'retl' instruction to return.
+ BuildMI(BB, V8::RETL, 0);
+ return;
+}
+
+static inline BasicBlock *getBlockAfter(BasicBlock *BB) {
+ Function::iterator I = BB; ++I; // Get iterator to next block
+ return I != BB->getParent()->end() ? &*I : 0;
+}
+
+/// visitBranchInst - Handles conditional and unconditional branches.
+///
+void V8ISel::visitBranchInst(BranchInst &I) {
+ BasicBlock *takenSucc = I.getSuccessor (0);
+ MachineBasicBlock *takenSuccMBB = MBBMap[takenSucc];
+ BB->addSuccessor (takenSuccMBB);
+ if (I.isConditional()) { // conditional branch
+ BasicBlock *notTakenSucc = I.getSuccessor (1);
+ MachineBasicBlock *notTakenSuccMBB = MBBMap[notTakenSucc];
+ BB->addSuccessor (notTakenSuccMBB);
+
+ // CondReg=(<condition>);
+ // If (CondReg==0) goto notTakenSuccMBB;
+ unsigned CondReg = getReg (I.getCondition ());
+ BuildMI (BB, V8::CMPri, 2).addSImm (0).addReg (CondReg);
+ BuildMI (BB, V8::BE, 1).addMBB (notTakenSuccMBB);
+ }
+ // goto takenSuccMBB;
+ BuildMI (BB, V8::BA, 1).addMBB (takenSuccMBB);
+}
+
+/// emitGEPOperation - Common code shared between visitGetElementPtrInst and
+/// constant expression GEP support.
+///
+void V8ISel::emitGEPOperation (MachineBasicBlock *MBB,
+ MachineBasicBlock::iterator IP,
+ Value *Src, User::op_iterator IdxBegin,
+ User::op_iterator IdxEnd, unsigned TargetReg) {
+ const TargetData &TD = TM.getTargetData ();
+ const Type *Ty = Src->getType ();
+ unsigned basePtrReg = getReg (Src, MBB, IP);
+
+ // GEPs have zero or more indices; we must perform a struct access
+ // or array access for each one.
+ for (GetElementPtrInst::op_iterator oi = IdxBegin, oe = IdxEnd; oi != oe;
+ ++oi) {
+ Value *idx = *oi;
+ unsigned nextBasePtrReg = makeAnotherReg (Type::UIntTy);
+ if (const StructType *StTy = dyn_cast<StructType> (Ty)) {
+ // It's a struct access. idx is the index into the structure,
+ // which names the field. Use the TargetData structure to
+ // pick out what the layout of the structure is in memory.
+ // Use the (constant) structure index's value to find the
+ // right byte offset from the StructLayout class's list of
+ // structure member offsets.
+ unsigned fieldIndex = cast<ConstantUInt> (idx)->getValue ();
+ unsigned memberOffset =
+ TD.getStructLayout (StTy)->MemberOffsets[fieldIndex];
+ // Emit an ADD to add memberOffset to the basePtr.
+ BuildMI (*MBB, IP, V8::ADDri, 2,
+ nextBasePtrReg).addReg (basePtrReg).addZImm (memberOffset);
+ // The next type is the member of the structure selected by the
+ // index.
+ Ty = StTy->getElementType (fieldIndex);
+ } else if (const SequentialType *SqTy = dyn_cast<SequentialType> (Ty)) {
+ // It's an array or pointer access: [ArraySize x ElementType].
+ // We want to add basePtrReg to (idxReg * sizeof ElementType). First, we
+ // must find the size of the pointed-to type (Not coincidentally, the next
+ // type is the type of the elements in the array).
+ Ty = SqTy->getElementType ();
+ unsigned elementSize = TD.getTypeSize (Ty);
+ unsigned idxReg = getReg (idx, MBB, IP);
+ unsigned OffsetReg = makeAnotherReg (Type::IntTy);
+ unsigned elementSizeReg = makeAnotherReg (Type::UIntTy);
+ copyConstantToRegister (MBB, IP,
+ ConstantUInt::get(Type::UIntTy, elementSize), elementSizeReg);
+ // Emit a SMUL to multiply the register holding the index by
+ // elementSize, putting the result in OffsetReg.
+ BuildMI (*MBB, IP, V8::SMULrr, 2,
+ OffsetReg).addReg (elementSizeReg).addReg (idxReg);
+ // Emit an ADD to add OffsetReg to the basePtr.
+ BuildMI (*MBB, IP, V8::ADDrr, 2,
+ nextBasePtrReg).addReg (basePtrReg).addReg (OffsetReg);
+ }
+ basePtrReg = nextBasePtrReg;
+ }
+ // After we have processed all the indices, the result is left in
+ // basePtrReg. Move it to the register where we were expected to
+ // put the answer.
+ BuildMI (BB, V8::ORrr, 1, TargetReg).addReg (V8::G0).addReg (basePtrReg);
+}
+
+void V8ISel::visitGetElementPtrInst (GetElementPtrInst &I) {
+ unsigned outputReg = getReg (I);
+ emitGEPOperation (BB, BB->end (), I.getOperand (0),
+ I.op_begin ()+1, I.op_end (), outputReg);
+}
+
+
+void V8ISel::visitBinaryOperator (Instruction &I) {