X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FSparc%2FSparcV8ISelSimple.cpp;h=fe11d84d50612fce783e066e85108ea7b400eeaf;hb=374b36d5cf56e070ed7a557314616fc48711d8ea;hp=b0f276439b0aad5bc6e0a22ddab2c7f4313a395f;hpb=6c868a4c17b6a540161d2f1cba2b9529cbb772ce;p=oota-llvm.git diff --git a/lib/Target/Sparc/SparcV8ISelSimple.cpp b/lib/Target/Sparc/SparcV8ISelSimple.cpp index b0f276439b0..fe11d84d506 100644 --- a/lib/Target/Sparc/SparcV8ISelSimple.cpp +++ b/lib/Target/Sparc/SparcV8ISelSimple.cpp @@ -13,13 +13,14 @@ #include "SparcV8.h" #include "SparcV8InstrInfo.h" -#include "Support/Debug.h" +#include "llvm/Support/Debug.h" #include "llvm/Instructions.h" -#include "llvm/IntrinsicLowering.h" #include "llvm/Pass.h" #include "llvm/Constants.h" +#include "llvm/CodeGen/IntrinsicLowering.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/SSARegMap.h" #include "llvm/Target/TargetMachine.h" @@ -57,6 +58,12 @@ namespace { Value *Src, User::op_iterator IdxBegin, User::op_iterator IdxEnd, unsigned TargetReg); + /// emitCastOperation - Common code shared between visitCastInst and + /// constant expression cast support. + /// + void emitCastOperation(MachineBasicBlock *BB,MachineBasicBlock::iterator IP, + Value *Src, const Type *DestTy, unsigned TargetReg); + /// visitBasicBlock - This method is called when we are visiting a new basic /// block. This simply creates a new MachineBasicBlock to emit code into /// and adds it to the current MachineFunction. Subsequent visit* for @@ -68,7 +75,7 @@ namespace { void visitBinaryOperator(Instruction &I); void visitShiftInst (ShiftInst &SI) { visitBinaryOperator (SI); } - void visitSetCondInst(Instruction &I); + void visitSetCondInst(SetCondInst &I); void visitCallInst(CallInst &I); void visitReturnInst(ReturnInst &I); void visitBranchInst(BranchInst &I); @@ -77,8 +84,7 @@ namespace { void visitStoreInst(StoreInst &I); void visitPHINode(PHINode &I) {} // PHI nodes handled by second pass void visitGetElementPtrInst(GetElementPtrInst &I); - - + void visitAllocaInst(AllocaInst &I); void visitInstruction(Instruction &I) { std::cerr << "Unhandled instruction: " << I; @@ -207,6 +213,9 @@ void V8ISel::copyConstantToRegister(MachineBasicBlock *MBB, emitGEPOperation(MBB, IP, CE->getOperand(0), CE->op_begin()+1, CE->op_end(), R); return; + case Instruction::Cast: + emitCastOperation(MBB, IP, CE->getOperand(0), CE->getType(), R); + return; default: std::cerr << "Copying this constant expr not yet handled: " << *CE; abort(); @@ -222,18 +231,10 @@ void V8ISel::copyConstantToRegister(MachineBasicBlock *MBB, // Copy the value into the register pair. // R = top(more-significant) half, R+1 = bottom(less-significant) half uint64_t Val = cast(C)->getRawValue(); - unsigned topHalf = Val & 0xffffffffU; - unsigned bottomHalf = Val >> 32; - unsigned HH = topHalf >> 10; - unsigned HM = topHalf & 0x03ff; - unsigned LM = bottomHalf >> 10; - unsigned LO = bottomHalf & 0x03ff; - BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg).addImm(HH); - BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (TmpReg) - .addImm (HM); - BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg2).addImm(LM); - BuildMI (*MBB, IP, V8::ORri, 2, R+1).addReg (TmpReg2) - .addImm (LO); + copyConstantToRegister(MBB, IP, ConstantUInt::get(Type::UIntTy, + Val >> 32), R); + copyConstantToRegister(MBB, IP, ConstantUInt::get(Type::UIntTy, + Val & 0xffffffffU), R+1); return; } @@ -242,72 +243,146 @@ void V8ISel::copyConstantToRegister(MachineBasicBlock *MBB, if (C->getType() == Type::BoolTy) { Val = (C == ConstantBool::True); } else { - ConstantInt *CI = dyn_cast (C); + ConstantInt *CI = cast (C); Val = CI->getRawValue (); } switch (Class) { - case cByte: - BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (V8::G0).addImm((uint8_t)Val); - return; - case cShort: { - unsigned TmpReg = makeAnotherReg (C->getType ()); - BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg) - .addImm (((uint16_t) Val) >> 10); - BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (TmpReg) - .addImm (((uint16_t) Val) & 0x03ff); - return; - } - case cInt: { - unsigned TmpReg = makeAnotherReg (C->getType ()); - BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg).addImm(((uint32_t)Val) >> 10); - BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (TmpReg) - .addImm (((uint32_t) Val) & 0x03ff); - return; - } + case cByte: Val = (int8_t) Val; break; + case cShort: Val = (int16_t) Val; break; + case cInt: Val = (int32_t) Val; break; default: std::cerr << "Offending constant: " << *C << "\n"; assert (0 && "Can't copy this kind of constant into register yet"); return; } + if (Val == 0) { + BuildMI (*MBB, IP, V8::ORrr, 2, R).addReg (V8::G0).addReg(V8::G0); + } else if (((int64_t)Val >= -4096) && ((int64_t)Val <= 4095)) { + BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (V8::G0).addSImm(Val); + } else { + unsigned TmpReg = makeAnotherReg (C->getType ()); + BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg) + .addSImm (((uint32_t) Val) >> 10); + BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (TmpReg) + .addSImm (((uint32_t) Val) & 0x03ff); + return; + } + } else if (ConstantFP *CFP = dyn_cast(C)) { + // We need to spill the constant to memory... + MachineConstantPool *CP = F->getConstantPool(); + unsigned CPI = CP->getConstantPoolIndex(CFP); + const Type *Ty = CFP->getType(); + unsigned TmpReg = makeAnotherReg (Type::UIntTy); + unsigned AddrReg = makeAnotherReg (Type::UIntTy); + + assert(Ty == Type::FloatTy || Ty == Type::DoubleTy && "Unknown FP type!"); + unsigned LoadOpcode = Ty == Type::FloatTy ? V8::LDFri : V8::LDDFri; + BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg).addConstantPoolIndex (CPI); + BuildMI (*MBB, IP, V8::ORri, 2, AddrReg).addReg (TmpReg).addConstantPoolIndex (CPI); + BuildMI (*MBB, IP, LoadOpcode, 2, R).addReg (AddrReg).addSImm (0); } else if (isa(C)) { // Copy zero (null pointer) to the register. - BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (V8::G0).addImm (0); - } else if (ConstantPointerRef *CPR = dyn_cast(C)) { + BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (V8::G0).addSImm (0); + } else if (GlobalValue *GV = dyn_cast(C)) { // Copy it with a SETHI/OR pair; the JIT + asmwriter should recognize // that SETHI %reg,global == SETHI %reg,%hi(global) and // OR %reg,global,%reg == OR %reg,%lo(global),%reg. unsigned TmpReg = makeAnotherReg (C->getType ()); - BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg).addGlobalAddress (CPR->getValue()); - BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (TmpReg) - .addGlobalAddress (CPR->getValue ()); + BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg).addGlobalAddress(GV); + BuildMI (*MBB, IP, V8::ORri, 2, R).addReg(TmpReg).addGlobalAddress(GV); } else { std::cerr << "Offending constant: " << *C << "\n"; assert (0 && "Can't copy this kind of constant into register yet"); } } -void V8ISel::LoadArgumentsToVirtualRegs (Function *F) { - unsigned ArgOffset = 0; +void V8ISel::LoadArgumentsToVirtualRegs (Function *LF) { + unsigned ArgOffset; static const unsigned IncomingArgRegs[] = { V8::I0, V8::I1, V8::I2, V8::I3, V8::I4, V8::I5 }; - assert (F->asize () < 7 - && "Can't handle loading excess call args off the stack yet"); - - for (Function::aiterator I = F->abegin(), E = F->aend(); I != E; ++I) { + // Add IMPLICIT_DEFs of input regs. + ArgOffset = 0; + for (Function::aiterator I = LF->abegin(), E = LF->aend(); + I != E && ArgOffset < 6; ++I, ++ArgOffset) { unsigned Reg = getReg(*I); switch (getClassB(I->getType())) { case cByte: case cShort: case cInt: - BuildMI(BB, V8::ORrr, 2, Reg).addReg (V8::G0) - .addReg (IncomingArgRegs[ArgOffset]); + case cFloat: + BuildMI(BB, V8::IMPLICIT_DEF, 0, IncomingArgRegs[ArgOffset]); + break; + case cDouble: + case cLong: + // Double and Long use register pairs. + BuildMI(BB, V8::IMPLICIT_DEF, 0, IncomingArgRegs[ArgOffset]); + ++ArgOffset; + if (ArgOffset < 6) + BuildMI(BB, V8::IMPLICIT_DEF, 0, IncomingArgRegs[ArgOffset]); break; default: - assert (0 && "Only <=32-bit, integral arguments currently handled"); + assert (0 && "type not handled"); return; } - ++ArgOffset; } + + ArgOffset = 0; + for (Function::aiterator I = LF->abegin(), E = LF->aend(); I != E; + ++I, ++ArgOffset) { + unsigned Reg = getReg(*I); + if (ArgOffset < 6) { + + switch (getClassB(I->getType())) { + case cByte: + case cShort: + case cInt: + BuildMI(BB, V8::ORrr, 2, Reg).addReg (V8::G0) + .addReg (IncomingArgRegs[ArgOffset]); + break; + case cFloat: { + // Single-fp args are passed in integer registers; go through + // memory to get them into FP registers. (Bleh!) + unsigned FltAlign = TM.getTargetData().getFloatAlignment(); + int FI = F->getFrameInfo()->CreateStackObject(4, FltAlign); + BuildMI (BB, V8::ST, 3).addFrameIndex (FI).addSImm (0) + .addReg (IncomingArgRegs[ArgOffset]); + BuildMI (BB, V8::LDFri, 2, Reg).addFrameIndex (FI).addSImm (0); + break; + } + default: + // FIXME: handle cDouble, cLong + assert (0 && "64-bit (double, long, etc.) function args not handled"); + return; + } + + } else { + + switch (getClassB(I->getType())) { + case cByte: + case cShort: + case cInt: { + int FI = F->getFrameInfo()->CreateFixedObject(4, 68 + (4 * ArgOffset)); + BuildMI (BB, V8::LD, 2, Reg).addFrameIndex (FI).addSImm(0); + break; + } + case cFloat: { + int FI = F->getFrameInfo()->CreateFixedObject(4, 68 + (4 * ArgOffset)); + BuildMI (BB, V8::LDFri, 2, Reg).addFrameIndex (FI).addSImm(0); + break; + } + case cDouble: { + int FI = F->getFrameInfo()->CreateFixedObject(8, 68 + (4 * ArgOffset)); + BuildMI (BB, V8::LDDFri, 2, Reg).addFrameIndex (FI).addSImm(0); + break; + } + default: + // FIXME: handle cLong + assert (0 && "64-bit integer (long/ulong) function args not handled"); + return; + } + } + } + } void V8ISel::SelectPHINodes() { @@ -440,12 +515,28 @@ bool V8ISel::runOnFunction(Function &Fn) { } void V8ISel::visitCastInst(CastInst &I) { - unsigned SrcReg = getReg (I.getOperand (0)); - unsigned DestReg = getReg (I); - const Type *oldTy = I.getOperand (0)->getType (); - const Type *newTy = I.getType (); - unsigned oldTyClass = getClassB (oldTy); - unsigned newTyClass = getClassB (newTy); + Value *Op = I.getOperand(0); + unsigned DestReg = getReg(I); + MachineBasicBlock::iterator MI = BB->end(); + emitCastOperation(BB, MI, Op, I.getType(), DestReg); +} + +/// emitCastOperation - Common code shared between visitCastInst and constant +/// expression cast support. +/// +void V8ISel::emitCastOperation(MachineBasicBlock *BB, + MachineBasicBlock::iterator IP, + Value *Src, const Type *DestTy, + unsigned DestReg) { + const Type *SrcTy = Src->getType(); + unsigned SrcClass = getClassB(SrcTy); + unsigned DestClass = getClassB(DestTy); + unsigned SrcReg = getReg(Src, BB, IP); + + const Type *oldTy = SrcTy; + const Type *newTy = DestTy; + unsigned oldTyClass = SrcClass; + unsigned newTyClass = DestClass; if (oldTyClass < cLong && newTyClass < cLong) { if (oldTyClass >= newTyClass) { @@ -453,13 +544,13 @@ void V8ISel::visitCastInst(CastInst &I) { // and do sign/zero extension (necessary if we change signedness). unsigned TmpReg1 = makeAnotherReg (newTy); unsigned TmpReg2 = makeAnotherReg (newTy); - BuildMI (BB, V8::ORrr, 2, TmpReg1).addReg (V8::G0).addReg (SrcReg); + BuildMI (*BB, IP, V8::ORrr, 2, TmpReg1).addReg (V8::G0).addReg (SrcReg); unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy)); - BuildMI (BB, V8::SLLri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1); + BuildMI (*BB, IP, V8::SLLri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1); if (newTy->isSigned ()) { // sign-extend with SRA - BuildMI(BB, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg2); + BuildMI(*BB, IP, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg2); } else { // zero-extend with SRL - BuildMI(BB, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg2); + BuildMI(*BB, IP, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg2); } } else { unsigned TmpReg1 = makeAnotherReg (oldTy); @@ -469,23 +560,79 @@ void V8ISel::visitCastInst(CastInst &I) { // wrt the input type, then make sure it's fully sign/zero-extended wrt // the output type. Kind of stupid, but simple... unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (oldTy)); - BuildMI (BB, V8::SLLri, 2, TmpReg1).addZImm (shiftWidth).addReg(SrcReg); + BuildMI (*BB, IP, V8::SLLri, 2, TmpReg1).addZImm (shiftWidth).addReg(SrcReg); if (oldTy->isSigned ()) { // sign-extend with SRA - BuildMI(BB, V8::SRAri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1); + BuildMI(*BB, IP, V8::SRAri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1); } else { // zero-extend with SRL - BuildMI(BB, V8::SRLri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1); + BuildMI(*BB, IP, V8::SRLri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1); } shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy)); - BuildMI (BB, V8::SLLri, 2, TmpReg3).addZImm (shiftWidth).addReg(TmpReg2); + BuildMI (*BB, IP, V8::SLLri, 2, TmpReg3).addZImm (shiftWidth).addReg(TmpReg2); if (newTy->isSigned ()) { // sign-extend with SRA - BuildMI(BB, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg3); + BuildMI(*BB, IP, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg3); } else { // zero-extend with SRL - BuildMI(BB, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg3); + BuildMI(*BB, IP, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg3); } } } else { - std::cerr << "Casts w/ long, fp, double still unsupported: " << I; - abort (); + if (newTyClass == cFloat) { + assert (oldTyClass != cLong && "cast long to float not implemented yet"); + switch (oldTyClass) { + case cFloat: + BuildMI (*BB, IP, V8::FMOVS, 1, DestReg).addReg (SrcReg); + break; + case cDouble: + BuildMI (*BB, IP, V8::FDTOS, 1, DestReg).addReg (SrcReg); + break; + default: { + unsigned FltAlign = TM.getTargetData().getFloatAlignment(); + // cast int to float. Store it to a stack slot and then load + // it using ldf into a floating point register. then do fitos. + unsigned TmpReg = makeAnotherReg (newTy); + int FI = F->getFrameInfo()->CreateStackObject(4, FltAlign); + BuildMI (*BB, IP, V8::ST, 3).addFrameIndex (FI).addSImm (0) + .addReg (SrcReg); + BuildMI (*BB, IP, V8::LDFri, 2, TmpReg).addFrameIndex (FI).addSImm (0); + BuildMI (*BB, IP, V8::FITOS, 1, DestReg).addReg(TmpReg); + break; + } + } + } else if (newTyClass == cDouble) { + assert (oldTyClass != cLong && "cast long to double not implemented yet"); + switch (oldTyClass) { + case cFloat: + BuildMI (*BB, IP, V8::FSTOD, 1, DestReg).addReg (SrcReg); + break; + case cDouble: // use double move pseudo-instr + BuildMI (*BB, IP, V8::FpMOVD, 1, DestReg).addReg (SrcReg); + break; + default: { + unsigned DoubleAlignment = TM.getTargetData().getDoubleAlignment(); + unsigned TmpReg = makeAnotherReg (newTy); + int FI = F->getFrameInfo()->CreateStackObject(8, DoubleAlignment); + BuildMI (*BB, IP, V8::ST, 3).addFrameIndex (FI).addSImm (0) + .addReg (SrcReg); + BuildMI (*BB, IP, V8::LDDFri, 2, TmpReg).addFrameIndex (FI).addSImm (0); + BuildMI (*BB, IP, V8::FITOD, 1, DestReg).addReg(TmpReg); + break; + } + } + } else if (newTyClass == cLong) { + if (oldTyClass == cLong) { + // Just copy it + BuildMI (*BB, IP, V8::ORrr, 2, DestReg).addReg (V8::G0).addReg (SrcReg); + BuildMI (*BB, IP, V8::ORrr, 2, DestReg+1).addReg (V8::G0) + .addReg (SrcReg+1); + } else { + std::cerr << "Cast still unsupported: SrcTy = " + << *SrcTy << ", DestTy = " << *DestTy << "\n"; + abort (); + } + } else { + std::cerr << "Cast still unsupported: SrcTy = " + << *SrcTy << ", DestTy = " << *DestTy << "\n"; + abort (); + } } } @@ -495,21 +642,28 @@ void V8ISel::visitLoadInst(LoadInst &I) { switch (getClassB (I.getType ())) { case cByte: if (I.getType ()->isSigned ()) - BuildMI (BB, V8::LDSBmr, 1, DestReg).addReg (PtrReg).addSImm(0); + BuildMI (BB, V8::LDSB, 2, DestReg).addReg (PtrReg).addSImm(0); else - BuildMI (BB, V8::LDUBmr, 1, DestReg).addReg (PtrReg).addSImm(0); + BuildMI (BB, V8::LDUB, 2, DestReg).addReg (PtrReg).addSImm(0); return; case cShort: if (I.getType ()->isSigned ()) - BuildMI (BB, V8::LDSHmr, 1, DestReg).addReg (PtrReg).addSImm(0); + BuildMI (BB, V8::LDSH, 2, DestReg).addReg (PtrReg).addSImm(0); else - BuildMI (BB, V8::LDUHmr, 1, DestReg).addReg (PtrReg).addSImm(0); + BuildMI (BB, V8::LDUH, 2, DestReg).addReg (PtrReg).addSImm(0); return; case cInt: - BuildMI (BB, V8::LDmr, 1, DestReg).addReg (PtrReg).addSImm(0); + BuildMI (BB, V8::LD, 2, DestReg).addReg (PtrReg).addSImm(0); return; case cLong: - BuildMI (BB, V8::LDDmr, 1, DestReg).addReg (PtrReg).addSImm(0); + BuildMI (BB, V8::LD, 2, DestReg).addReg (PtrReg).addSImm(0); + BuildMI (BB, V8::LD, 2, DestReg+1).addReg (PtrReg).addSImm(4); + return; + case cFloat: + BuildMI (BB, V8::LDFri, 2, DestReg).addReg (PtrReg).addSImm(0); + return; + case cDouble: + BuildMI (BB, V8::LDDFri, 2, DestReg).addReg (PtrReg).addSImm(0); return; default: std::cerr << "Load instruction not handled: " << I; @@ -524,16 +678,23 @@ void V8ISel::visitStoreInst(StoreInst &I) { unsigned PtrReg = getReg (I.getOperand (1)); switch (getClassB (SrcVal->getType ())) { case cByte: - BuildMI (BB, V8::STBrm, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg); + BuildMI (BB, V8::STB, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg); return; case cShort: - BuildMI (BB, V8::STHrm, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg); + BuildMI (BB, V8::STH, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg); return; case cInt: - BuildMI (BB, V8::STrm, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg); + BuildMI (BB, V8::ST, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg); return; case cLong: - BuildMI (BB, V8::STDrm, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg); + 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; @@ -543,6 +704,16 @@ void V8ISel::visitStoreInst(StoreInst &I) { } 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, @@ -550,23 +721,64 @@ void V8ISel::visitCallInst(CallInst &I) { for (unsigned i = 1; i < 7; ++i) if (i < I.getNumOperands ()) { unsigned ArgReg = getReg (I.getOperand (i)); - // Schlep it over into the incoming arg register - BuildMI (BB, V8::ORrr, 2, OutgoingArgRegs[i - 1]).addReg (V8::G0) - .addReg (ArgReg); + 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 if (getClassB (I.getOperand (i)->getType ()) == cDouble) { + // Double-fp args are passed in pairs of integer registers; go through + // memory to get them out of FP registers. (Bleh!) + assert (i <= 5 && "Can't deal with double-fp args past #5 yet"); + unsigned DblAlign = TM.getTargetData().getDoubleAlignment(); + int FI = F->getFrameInfo()->CreateStackObject(8, DblAlign); + BuildMI (BB, V8::STDFri, 3).addFrameIndex (FI).addSImm (0) + .addReg (ArgReg); + BuildMI (BB, V8::LD, 2, OutgoingArgRegs[i - 1]).addFrameIndex (FI) + .addSImm (0); + BuildMI (BB, V8::LD, 2, OutgoingArgRegs[i]).addFrameIndex (FI) + .addSImm (4); + } else { + assert (0 && "64-bit (double, long, etc.) 'call' opnds not handled"); + } } - BuildMI (BB, V8::CALL, 1).addGlobalAddress(I.getCalledFunction (), true); + // 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); - // Deal w/ return value switch (getClass (I.getType ())) { case cByte: case cShort: case cInt: - // Schlep it over into the destination register 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; + case cDouble: + BuildMI (BB, V8::FpMOVD, 2, DestReg).addReg(V8::D0); + break; + case cLong: + BuildMI (BB, V8::ORrr, 2, DestReg).addReg(V8::G0).addReg(V8::O0); + BuildMI (BB, V8::ORrr, 2, DestReg+1).addReg(V8::G0).addReg(V8::O1); + break; default: std::cerr << "Return type of call instruction not handled: " << I; abort (); @@ -583,6 +795,16 @@ void V8ISel::visitReturnInst(ReturnInst &I) { // 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, 1, V8::F0).addReg(RetValReg); + break; + case cDouble: + BuildMI (BB, V8::FpMOVD, 1, V8::D0).addReg(RetValReg); + 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 (); @@ -629,7 +851,7 @@ void V8ISel::emitGEPOperation (MachineBasicBlock *MBB, User::op_iterator IdxEnd, unsigned TargetReg) { const TargetData &TD = TM.getTargetData (); const Type *Ty = Src->getType (); - unsigned basePtrReg = getReg (Src); + unsigned basePtrReg = getReg (Src, MBB, IP); // GEPs have zero or more indices; we must perform a struct access // or array access for each one. @@ -663,8 +885,8 @@ void V8ISel::emitGEPOperation (MachineBasicBlock *MBB, unsigned idxReg = getReg (idx, MBB, IP); unsigned OffsetReg = makeAnotherReg (Type::IntTy); unsigned elementSizeReg = makeAnotherReg (Type::UIntTy); - BuildMI (*MBB, IP, V8::ORri, 2, - elementSizeReg).addZImm (elementSize).addReg (V8::G0); + 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, @@ -693,12 +915,39 @@ void V8ISel::visitBinaryOperator (Instruction &I) { unsigned Op0Reg = getReg (I.getOperand (0)); unsigned Op1Reg = getReg (I.getOperand (1)); + unsigned Class = getClassB (I.getType()); + unsigned OpCase = ~0; + + if (Class > cLong) { + switch (I.getOpcode ()) { + case Instruction::Add: OpCase = 0; break; + case Instruction::Sub: OpCase = 1; break; + case Instruction::Mul: OpCase = 2; break; + case Instruction::Div: OpCase = 3; break; + default: visitInstruction (I); return; + } + static unsigned Opcodes[] = { V8::FADDS, V8::FADDD, + V8::FSUBS, V8::FSUBD, + V8::FMULS, V8::FMULD, + V8::FDIVS, V8::FDIVD }; + BuildMI (BB, Opcodes[2*OpCase + (Class - cFloat)], 2, DestReg) + .addReg (Op0Reg).addReg (Op1Reg); + return; + } + unsigned ResultReg = DestReg; - if (getClassB(I.getType()) != cInt) + if (Class != cInt && Class != cLong) ResultReg = makeAnotherReg (I.getType ()); - unsigned OpCase = ~0; - // FIXME: support long, ulong, fp. + if (Class == cLong) { + DEBUG (std::cerr << "Class = cLong\n"); + DEBUG (std::cerr << "Op0Reg = " << Op0Reg << ", " << Op0Reg+1 << "\n"); + DEBUG (std::cerr << "Op1Reg = " << Op1Reg << ", " << Op1Reg+1 << "\n"); + DEBUG (std::cerr << "ResultReg = " << ResultReg << ", " << ResultReg+1 << "\n"); + DEBUG (std::cerr << "DestReg = " << DestReg << ", " << DestReg+1 << "\n"); + } + + // FIXME: support long, ulong. switch (I.getOpcode ()) { case Instruction::Add: OpCase = 0; break; case Instruction::Sub: OpCase = 1; break; @@ -740,15 +989,15 @@ void V8ISel::visitBinaryOperator (Instruction &I) { return; } + static const unsigned Opcodes[] = { + V8::ADDrr, V8::SUBrr, V8::SMULrr, V8::ANDrr, V8::ORrr, V8::XORrr, + V8::SLLrr, V8::SRLrr, V8::SRArr + }; if (OpCase != ~0U) { - static const unsigned Opcodes[] = { - V8::ADDrr, V8::SUBrr, V8::SMULrr, V8::ANDrr, V8::ORrr, V8::XORrr, - V8::SLLrr, V8::SRLrr, V8::SRArr - }; BuildMI (BB, Opcodes[OpCase], 2, ResultReg).addReg (Op0Reg).addReg (Op1Reg); } - switch (getClass (I.getType ())) { + switch (getClassB (I.getType ())) { case cByte: if (I.getType ()->isSigned ()) { // add byte BuildMI (BB, V8::ANDri, 2, DestReg).addReg (ResultReg).addZImm (0xff); @@ -770,22 +1019,38 @@ void V8ISel::visitBinaryOperator (Instruction &I) { } break; case cInt: - // Nothing todo here. + // Nothing to do here. + break; + case cLong: + // Only support and, or, xor. + if (OpCase < 3 || OpCase > 5) { + visitInstruction (I); + return; + } + // Do the other half of the value: + BuildMI (BB, Opcodes[OpCase], 2, ResultReg+1).addReg (Op0Reg+1) + .addReg (Op1Reg+1); break; default: visitInstruction (I); - return; } } -void V8ISel::visitSetCondInst(Instruction &I) { +void V8ISel::visitSetCondInst(SetCondInst &I) { unsigned Op0Reg = getReg (I.getOperand (0)); unsigned Op1Reg = getReg (I.getOperand (1)); unsigned DestReg = getReg (I); const Type *Ty = I.getOperand (0)->getType (); // Compare the two values. - BuildMI(BB, V8::SUBCCrr, 2, V8::G0).addReg(Op0Reg).addReg(Op1Reg); + assert (getClass (Ty) != cLong && "can't setcc on longs yet"); + if (getClass (Ty) < cLong) { + BuildMI(BB, V8::SUBCCrr, 2, V8::G0).addReg(Op0Reg).addReg(Op1Reg); + } else if (getClass (Ty) == cFloat) { + BuildMI(BB, V8::FCMPS, 2).addReg(Op0Reg).addReg(Op1Reg); + } else if (getClass (Ty) == cDouble) { + BuildMI(BB, V8::FCMPD, 2).addReg(Op0Reg).addReg(Op1Reg); + } unsigned BranchIdx; switch (I.getOpcode()) { @@ -797,17 +1062,20 @@ void V8ISel::visitSetCondInst(Instruction &I) { case Instruction::SetLE: BranchIdx = 4; break; case Instruction::SetGE: BranchIdx = 5; break; } - static unsigned OpcodeTab[12] = { - // LLVM SparcV8 - // unsigned signed - V8::BE, V8::BE, // seteq = be be - V8::BNE, V8::BNE, // setne = bne bne - V8::BCS, V8::BL, // setlt = bcs bl - V8::BGU, V8::BG, // setgt = bgu bg - V8::BLEU, V8::BLE, // setle = bleu ble - V8::BCC, V8::BGE // setge = bcc bge + unsigned Column = 0; + if (Ty->isSigned()) ++Column; + if (Ty->isFloatingPoint()) ++Column; + static unsigned OpcodeTab[3*6] = { + // LLVM SparcV8 + // unsigned signed fp + V8::BE, V8::BE, V8::FBE, // seteq = be be fbe + V8::BNE, V8::BNE, V8::FBNE, // setne = bne bne fbne + V8::BCS, V8::BL, V8::FBL, // setlt = bcs bl fbl + V8::BGU, V8::BG, V8::FBG, // setgt = bgu bg fbg + V8::BLEU, V8::BLE, V8::FBLE, // setle = bleu ble fble + V8::BCC, V8::BGE, V8::FBGE // setge = bcc bge fbge }; - unsigned Opcode = OpcodeTab[2*BranchIdx + (Ty->isSigned() ? 1 : 0)]; + unsigned Opcode = OpcodeTab[3*BranchIdx + Column]; MachineBasicBlock *thisMBB = BB; const BasicBlock *LLVM_BB = BB->getBasicBlock (); @@ -865,7 +1133,35 @@ void V8ISel::visitSetCondInst(Instruction &I) { .addMBB (copy0MBB).addReg (TrueValue).addMBB (copy1MBB); } +void V8ISel::visitAllocaInst(AllocaInst &I) { + // Find the data size of the alloca inst's getAllocatedType. + const Type *Ty = I.getAllocatedType(); + unsigned TySize = TM.getTargetData().getTypeSize(Ty); + unsigned ArraySizeReg = getReg (I.getArraySize ()); + unsigned TySizeReg = getReg (ConstantUInt::get (Type::UIntTy, TySize)); + unsigned TmpReg1 = makeAnotherReg (Type::UIntTy); + unsigned TmpReg2 = makeAnotherReg (Type::UIntTy); + unsigned StackAdjReg = makeAnotherReg (Type::UIntTy); + + // StackAdjReg = (ArraySize * TySize) rounded up to nearest doubleword boundary + BuildMI (BB, V8::UMULrr, 2, TmpReg1).addReg (ArraySizeReg).addReg (TySizeReg); + + // Round up TmpReg1 to nearest doubleword boundary: + BuildMI (BB, V8::ADDri, 2, TmpReg2).addReg (TmpReg1).addSImm (7); + BuildMI (BB, V8::ANDri, 2, StackAdjReg).addReg (TmpReg2).addSImm (-8); + + // Subtract size from stack pointer, thereby allocating some space. + BuildMI (BB, V8::SUBrr, 2, V8::SP).addReg (V8::SP).addReg (StackAdjReg); + + // Put a pointer to the space into the result register, by copying + // the stack pointer. + BuildMI (BB, V8::ADDri, 2, getReg(I)).addReg (V8::SP).addSImm (96); + + // Inform the Frame Information that we have just allocated a variable-sized + // object. + F->getFrameInfo()->CreateVariableSizedObject(); +} /// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the /// function, lowering any calls to unknown intrinsic functions into the