X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FX86%2FInstSelectSimple.cpp;h=217b219ba2a4ae47e6d7f5420d61147a06a5a9af;hb=d474e9cdce5aa061e9a340040246592737667cb5;hp=55bf65b2f58b686024307d37b8176166eca3900b;hpb=0d2cf3a533572ee2f4a08f997499d18e41a37176;p=oota-llvm.git diff --git a/lib/Target/X86/InstSelectSimple.cpp b/lib/Target/X86/InstSelectSimple.cpp index 55bf65b2f58..217b219ba2a 100644 --- a/lib/Target/X86/InstSelectSimple.cpp +++ b/lib/Target/X86/InstSelectSimple.cpp @@ -430,6 +430,22 @@ ISel::visitCallInst (CallInst & CI) // Adjust the stack by `bytesPushed' amount if non-zero if (bytesPushed > 0) BuildMI (BB, X86::ADDri32, 2).addReg(X86::ESP).addZImm(bytesPushed); + + // If there is a return value, scavenge the result from the location the call + // leaves it in... + // + if (CI.getType() != Type::VoidTy) { + switch (getClass(CI.getType())) { + case cInt: + BuildMI(BB, X86::MOVrr32, 1, getReg(CI)).addReg(X86::EAX); + break; + + default: + std::cerr << "Cannot get return value for call of type '" + << *CI.getType() << "'\n"; + visitInstruction(CI); + } + } } /// visitSimpleBinary - Implement simple binary operators for integral types... @@ -649,45 +665,73 @@ void ISel::visitPHINode(PHINode &PN) { void ISel::visitCastInst (CastInst &CI) { -//> cast larger int to smaller int --> copy least significant byte/word w/ mov? -// -//I'm not really sure what to do with this. We could insert a pseudo-op -//that says take the low X bits of a Y bit register, but for now we can just -//force the value into, say, EAX, then rip out AL or AX. The advantage of -//the former is that the register allocator could use any register it wants, -//but for now this obviously doesn't matter. :) - const Type *targetType = CI.getType (); Value *operand = CI.getOperand (0); unsigned int operandReg = getReg (operand); const Type *sourceType = operand->getType (); unsigned int destReg = getReg (CI); - - // cast to bool: - if (targetType == Type::BoolTy) { - // Emit Compare - BuildMI (BB, X86::CMPri8, 2).addReg (operandReg).addZImm (0); - // Emit Set-if-not-zero - BuildMI (BB, X86::SETNEr, 1, destReg); - return; - } - -// if size of target type == size of source type -// Emit Mov reg(target) <- reg(source) - -// if size of target type > size of source type -// if both types are integer types -// if source type is signed -// sbyte to short, ushort: Emit movsx 8->16 -// sbyte to int, uint: Emit movsx 8->32 -// short to int, uint: Emit movsx 16->32 -// else if source type is unsigned -// ubyte to short, ushort: Emit movzx 8->16 -// ubyte to int, uint: Emit movzx 8->32 -// ushort to int, uint: Emit movzx 16->32 -// if both types are fp types -// float to double: Emit fstp, fld (???) - + // + // Currently we handle: + // + // 1) cast * to bool + // + // 2) cast {sbyte, ubyte} to {sbyte, ubyte} + // cast {short, ushort} to {ushort, short} + // cast {int, uint, ptr} to {int, uint, ptr} + // + // 3) cast {sbyte, ubyte} to {ushort, short} + // cast {sbyte, ubyte} to {int, uint, ptr} + // cast {short, ushort} to {int, uint, ptr} + // + // 4) cast {int, uint, ptr} to {short, ushort} + // cast {int, uint, ptr} to {sbyte, ubyte} + // cast {short, ushort} to {sbyte, ubyte} + // + // 1) Implement casts to bool by using compare on the operand followed + // by set if not zero on the result. + if (targetType == Type::BoolTy) + { + BuildMI (BB, X86::CMPri8, 2).addReg (operandReg).addZImm (0); + BuildMI (BB, X86::SETNEr, 1, destReg); + return; + } + // 2) Implement casts between values of the same type class (as determined + // by getClass) by using a register-to-register move. + unsigned int srcClass = getClass (sourceType); + unsigned int targClass = getClass (targetType); + static const unsigned regRegMove[] = { + X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 + }; + if ((srcClass < 3) && (targClass < 3) && (srcClass == targClass)) + { + BuildMI (BB, regRegMove[srcClass], 1, destReg).addReg (operandReg); + return; + } + // 3) Handle cast of SMALLER int to LARGER int using a move with sign + // extension or zero extension, depending on whether the source type + // was signed. + if ((srcClass < 3) && (targClass < 3) && (srcClass < targClass)) + { + static const unsigned ops[] = { + X86::MOVSXr16r8, X86::MOVSXr32r8, X86::MOVSXr32r16, + X86::MOVZXr16r8, X86::MOVZXr32r8, X86::MOVZXr32r16 + }; + unsigned srcSigned = sourceType->isSigned (); + BuildMI (BB, ops[3 * srcSigned + srcClass + targClass - 1], 1, + destReg).addReg (operandReg); + return; + } + // 4) Handle cast of LARGER int to SMALLER int using a move to EAX + // followed by a move out of AX or AL. + if ((srcClass < 3) && (targClass < 3) && (srcClass > targClass)) + { + static const unsigned AReg[] = { X86::AL, X86::AX, X86::EAX }; + BuildMI (BB, regRegMove[srcClass], 1, + AReg[srcClass]).addReg (operandReg); + BuildMI (BB, regRegMove[targClass], 1, destReg).addReg (AReg[srcClass]); + return; + } + // Anything we haven't handled already, we can't (yet) handle at all. visitInstruction (CI); }