RegMap.clear();
MBBMap.clear();
F = 0;
- return false; // We never modify the LLVM itself.
+ // We always build a machine code representation for the function
+ return true;
}
virtual const char *getPassName() const {
void visitBranchInst(BranchInst &BI);
struct ValueRecord {
+ Value *Val;
unsigned Reg;
const Type *Ty;
- ValueRecord(unsigned R, const Type *T) : Reg(R), Ty(T) {}
+ ValueRecord(unsigned R, const Type *T) : Val(0), Reg(R), Ty(T) {}
+ ValueRecord(Value *V) : Val(V), Reg(0), Ty(V->getType()) {}
};
void doCall(const ValueRecord &Ret, MachineInstr *CallMI,
const std::vector<ValueRecord> &Args);
/// of the long value.
///
unsigned makeAnotherReg(const Type *Ty) {
+ assert(dynamic_cast<const X86RegisterInfo*>(TM.getRegisterInfo()) &&
+ "Current target doesn't have X86 reg info??");
+ const X86RegisterInfo *MRI =
+ static_cast<const X86RegisterInfo*>(TM.getRegisterInfo());
if (Ty == Type::LongTy || Ty == Type::ULongTy) {
- const TargetRegisterClass *RC =
- TM.getRegisterInfo()->getRegClassForType(Type::IntTy);
+ const TargetRegisterClass *RC = MRI->getRegClassForType(Type::IntTy);
// Create the lower part
F->getSSARegMap()->createVirtualRegister(RC);
// Create the upper part.
}
// Add the mapping of regnumber => reg class to MachineFunction
- const TargetRegisterClass *RC =
- TM.getRegisterInfo()->getRegClassForType(Ty);
+ const TargetRegisterClass *RC = MRI->getRegClassForType(Ty);
return F->getSSARegMap()->createVirtualRegister(RC);
}
if (Class == cLong) {
// Copy the value into the register pair.
- uint64_t Val;
- if (C->getType()->isSigned())
- Val = cast<ConstantSInt>(C)->getValue();
- else
- Val = cast<ConstantUInt>(C)->getValue();
-
+ uint64_t Val = cast<ConstantInt>(C)->getRawValue();
BMI(MBB, IP, X86::MOVir32, 1, R).addZImm(Val & 0xFFFFFFFF);
BMI(MBB, IP, X86::MOVir32, 1, R+1).addZImm(Val >> 32);
return;
if (C->getType() == Type::BoolTy) {
BMI(MBB, IP, X86::MOVir8, 1, R).addZImm(C == ConstantBool::True);
- } else if (C->getType()->isSigned()) {
- ConstantSInt *CSI = cast<ConstantSInt>(C);
- BMI(MBB, IP, IntegralOpcodeTab[Class], 1, R).addZImm(CSI->getValue());
} else {
- ConstantUInt *CUI = cast<ConstantUInt>(C);
- BMI(MBB, IP, IntegralOpcodeTab[Class], 1, R).addZImm(CUI->getValue());
+ ConstantInt *CI = cast<ConstantInt>(C);
+ BMI(MBB, IP, IntegralOpcodeTab[Class], 1, R).addZImm(CI->getRawValue());
}
} else if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
double Value = CFP->getValue();
// Special case handling of: cmp R, i
if (Class == cByte || Class == cShort || Class == cInt)
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
- uint64_t Op1v;
- if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(CI))
- Op1v = CSI->getValue();
- else
- Op1v = cast<ConstantUInt>(CI)->getValue();
+ uint64_t Op1v = cast<ConstantInt>(CI)->getRawValue();
+
// Mask off any upper bits of the constant, if there are any...
Op1v &= (1ULL << (8 << Class)) - 1;
BuildMI(BB, SetCCOpcodeTab[0][OpNum], 0, X86::AL);
BuildMI(BB, X86::CMPrr32, 2).addReg(Op0r+1).addReg(Op1r+1);
BuildMI(BB, SetCCOpcodeTab[isSigned][OpNum], 0, X86::BL);
+ BuildMI(BB, X86::IMPLICIT_DEF, 0, X86::BH);
+ BuildMI(BB, X86::IMPLICIT_DEF, 0, X86::AH);
BuildMI(BB, X86::CMOVErr16, 2, X86::BX).addReg(X86::BX).addReg(X86::AX);
// NOTE: visitSetCondInst knows that the value is dumped into the BL
// register at this point for long values...
/// operand, in the specified target register.
void ISel::promote32(unsigned targetReg, const ValueRecord &VR) {
bool isUnsigned = VR.Ty->isUnsigned();
+
+ // Make sure we have the register number for this value...
+ unsigned Reg = VR.Val ? getReg(VR.Val) : VR.Reg;
+
switch (getClassB(VR.Ty)) {
case cByte:
// Extend value into target register (8->32)
if (isUnsigned)
- BuildMI(BB, X86::MOVZXr32r8, 1, targetReg).addReg(VR.Reg);
+ BuildMI(BB, X86::MOVZXr32r8, 1, targetReg).addReg(Reg);
else
- BuildMI(BB, X86::MOVSXr32r8, 1, targetReg).addReg(VR.Reg);
+ BuildMI(BB, X86::MOVSXr32r8, 1, targetReg).addReg(Reg);
break;
case cShort:
// Extend value into target register (16->32)
if (isUnsigned)
- BuildMI(BB, X86::MOVZXr32r16, 1, targetReg).addReg(VR.Reg);
+ BuildMI(BB, X86::MOVZXr32r16, 1, targetReg).addReg(Reg);
else
- BuildMI(BB, X86::MOVSXr32r16, 1, targetReg).addReg(VR.Reg);
+ BuildMI(BB, X86::MOVSXr32r16, 1, targetReg).addReg(Reg);
break;
case cInt:
// Move value into target register (32->32)
- BuildMI(BB, X86::MOVrr32, 1, targetReg).addReg(VR.Reg);
+ BuildMI(BB, X86::MOVrr32, 1, targetReg).addReg(Reg);
break;
default:
assert(0 && "Unpromotable operand class in promote32");
// Arguments go on the stack in reverse order, as specified by the ABI.
unsigned ArgOffset = 0;
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
- unsigned ArgReg = Args[i].Reg;
+ unsigned ArgReg = Args[i].Val ? getReg(Args[i].Val) : Args[i].Reg;
switch (getClassB(Args[i].Ty)) {
case cByte:
case cShort: {
std::vector<ValueRecord> Args;
for (unsigned i = 1, e = CI.getNumOperands(); i != e; ++i)
- Args.push_back(ValueRecord(getReg(CI.getOperand(i)),
- CI.getOperand(i)->getType()));
+ Args.push_back(ValueRecord(CI.getOperand(i)));
unsigned DestReg = CI.getType() != Type::VoidTy ? getReg(CI) : 0;
doCall(ValueRecord(DestReg, CI.getType()), TheCall, Args);
addDirectMem(BuildMI(BB, X86::MOVrm32, 5), TmpReg2).addReg(TmpReg1);
return;
+ case LLVMIntrinsic::longjmp:
+ BuildMI(X86::CALLpcrel32, 1).addExternalSymbol("abort", true);
+ return;
+
+ case LLVMIntrinsic::setjmp:
+ // Setjmp always returns zero...
+ BuildMI(BB, X86::MOVir32, 1, getReg(CI)).addZImm(0);
+ return;
default: assert(0 && "Unknown intrinsic for X86!");
}
}
assert(Class < 3 && "General code handles 64-bit integer types!");
unsigned Opcode = OpcodeTab[OperatorClass][Class];
unsigned Op0r = getReg(Op0, BB, IP);
- uint64_t Op1v;
- if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(Op1C))
- Op1v = CSI->getValue();
- else
- Op1v = cast<ConstantUInt>(Op1C)->getValue();
+ uint64_t Op1v = cast<ConstantInt>(Op1C)->getRawValue();
// Mask off any upper bits of the constant, if there are any...
Op1v &= (1ULL << (8 << Class)) - 1;
/// instructions work differently for signed and unsigned operands.
///
void ISel::visitDivRem(BinaryOperator &I) {
- unsigned Class = getClass(I.getType());
- unsigned Op0Reg = getReg(I.getOperand(0));
- unsigned Op1Reg = getReg(I.getOperand(1));
- unsigned ResultReg = getReg(I);
+ unsigned Class = getClass(I.getType());
+ unsigned Op0Reg, Op1Reg, ResultReg = getReg(I);
switch (Class) {
case cFP: // Floating point divide
- if (I.getOpcode() == Instruction::Div)
+ if (I.getOpcode() == Instruction::Div) {
+ Op0Reg = getReg(I.getOperand(0));
+ Op1Reg = getReg(I.getOperand(1));
BuildMI(BB, X86::FpDIV, 2, ResultReg).addReg(Op0Reg).addReg(Op1Reg);
- else { // Floating point remainder...
+ } else { // Floating point remainder...
MachineInstr *TheCall =
BuildMI(X86::CALLpcrel32, 1).addExternalSymbol("fmod", true);
std::vector<ValueRecord> Args;
- Args.push_back(ValueRecord(Op0Reg, Type::DoubleTy));
- Args.push_back(ValueRecord(Op1Reg, Type::DoubleTy));
+ Args.push_back(ValueRecord(I.getOperand(0)));
+ Args.push_back(ValueRecord(I.getOperand(1)));
doCall(ValueRecord(ResultReg, Type::DoubleTy), TheCall, Args);
}
return;
BuildMI(X86::CALLpcrel32, 1).addExternalSymbol(FnName[NameIdx], true);
std::vector<ValueRecord> Args;
- Args.push_back(ValueRecord(Op0Reg, Type::LongTy));
- Args.push_back(ValueRecord(Op1Reg, Type::LongTy));
+ Args.push_back(ValueRecord(I.getOperand(0)));
+ Args.push_back(ValueRecord(I.getOperand(1)));
doCall(ValueRecord(ResultReg, Type::LongTy), TheCall, Args);
return;
}
static const unsigned Regs[] ={ X86::AL , X86::AX , X86::EAX };
static const unsigned MovOpcode[]={ X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 };
- static const unsigned ExtOpcode[]={ X86::CBW , X86::CWD , X86::CDQ };
+ static const unsigned SarOpcode[]={ X86::SARir8, X86::SARir16, X86::SARir32 };
static const unsigned ClrOpcode[]={ X86::XORrr8, X86::XORrr16, X86::XORrr32 };
static const unsigned ExtRegs[] ={ X86::AH , X86::DX , X86::EDX };
unsigned ExtReg = ExtRegs[Class];
// Put the first operand into one of the A registers...
+ Op0Reg = getReg(I.getOperand(0));
BuildMI(BB, MovOpcode[Class], 1, Reg).addReg(Op0Reg);
if (isSigned) {
// Emit a sign extension instruction...
- BuildMI(BB, ExtOpcode[Class], 0);
+ unsigned ShiftResult = makeAnotherReg(I.getType());
+ BuildMI(BB, SarOpcode[Class], 2, ShiftResult).addReg(Op0Reg).addZImm(31);
+ BuildMI(BB, MovOpcode[Class], 1, ExtReg).addReg(ShiftResult);
} else {
// If unsigned, emit a zeroing instruction... (reg = xor reg, reg)
BuildMI(BB, ClrOpcode[Class], 2, ExtReg).addReg(ExtReg).addReg(ExtReg);
}
// Emit the appropriate divide or remainder instruction...
+ Op1Reg = getReg(I.getOperand(1));
BuildMI(BB, DivOpcode[isSigned][Class], 1).addReg(Op1Reg);
// Figure out which register we want to pick the result out of...
unsigned SrcAddrReg = getReg(I.getOperand(0));
unsigned DestReg = getReg(I);
- unsigned Class = getClass(I.getType());
+ unsigned Class = getClassB(I.getType());
switch (Class) {
case cFP: {
MachineBasicBlock::iterator MBBI = BB->end();
unsigned ValReg = getReg(I.getOperand(0));
unsigned AddressReg = getReg(I.getOperand(1));
- unsigned Class = getClass(I.getOperand(0)->getType());
+ unsigned Class = getClassB(I.getOperand(0)->getType());
switch (Class) {
case cLong:
if (isLittleEndian) {
case cByte: StoreTy = Type::ShortTy; StoreClass = cShort; break;
case cShort: StoreTy = Type::IntTy; StoreClass = cInt; break;
case cInt: StoreTy = Type::LongTy; StoreClass = cLong; break;
- case cLong:
- assert(0 &&"FIXME not implemented: cast FP to unsigned long long");
- abort();
+ // The following treatment of cLong may not be perfectly right,
+ // but it survives chains of casts of the form
+ // double->ulong->double.
+ case cLong: StoreTy = Type::LongTy; StoreClass = cLong; break;
default: assert(0 && "Unknown store class!");
}
unsigned Op1Reg = getReg(I.getOperand(0));
MachineBasicBlock::iterator MBBI = BB->end();
doMultiply(BB, MBBI, Arg, Type::UIntTy, Op0Reg, Op1Reg);
-
-
}
std::vector<ValueRecord> Args;
///
void ISel::visitFreeInst(FreeInst &I) {
std::vector<ValueRecord> Args;
- Args.push_back(ValueRecord(getReg(I.getOperand(0)),
- I.getOperand(0)->getType()));
+ Args.push_back(ValueRecord(I.getOperand(0)));
MachineInstr *TheCall = BuildMI(X86::CALLpcrel32,
1).addExternalSymbol("free", true);
doCall(ValueRecord(0, Type::VoidTy), TheCall, Args);
}
-/// createSimpleX86InstructionSelector - This pass converts an LLVM function
+/// createX86SimpleInstructionSelector - This pass converts an LLVM function
/// into a machine code representation is a very simple peep-hole fashion. The
/// generated code sucks but the implementation is nice and simple.
///
-Pass *createSimpleX86InstructionSelector(TargetMachine &TM) {
+FunctionPass *createX86SimpleInstructionSelector(TargetMachine &TM) {
return new ISel(TM);
}