Changes in directory llvm/lib/Target/CBackend:
Writer.cpp updated: 1.272.2.6 -> 1.272.2.7 --- Log message: Round 2 of DIV updates. --- Diffs of the changes: (+152 -4) Writer.cpp | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 152 insertions(+), 4 deletions(-) Index: llvm/lib/Target/CBackend/Writer.cpp diff -u llvm/lib/Target/CBackend/Writer.cpp:1.272.2.6 llvm/lib/Target/CBackend/Writer.cpp:1.272.2.7 --- llvm/lib/Target/CBackend/Writer.cpp:1.272.2.6 Mon Oct 23 13:13:27 2006 +++ llvm/lib/Target/CBackend/Writer.cpp Wed Oct 25 20:58:05 2006 @@ -121,6 +121,8 @@ void writeOperand(Value *Operand); void writeOperandInternal(Value *Operand); + void writeOperandWithCast(Value* Operand, unsigned Opcode); + bool writeInstructionCast(const Instruction &I); private : void lowerIntrinsics(Function &F); @@ -136,6 +138,8 @@ void printLoop(Loop *L); void printConstant(Constant *CPV); + void printConstantWithCast(Constant *CPV, unsigned Opcode); + bool printConstExprCast(const ConstantExpr *CE); void printConstantArray(ConstantArray *CPA); void printConstantPacked(ConstantPacked *CP); @@ -604,7 +608,8 @@ case Instruction::Shl: case Instruction::Shr: Out << '('; - printConstant(CE->getOperand(0)); + bool NeedsClosingParens = printConstExprCast(CE); + printConstantWithCast(CE->getOperand(0), CE->getOpcode()); switch (CE->getOpcode()) { case Instruction::Add: Out << " + "; break; case Instruction::Sub: Out << " - "; break; @@ -628,7 +633,9 @@ case Instruction::Shr: Out << " >> "; break; default: assert(0 && "Illegal opcode here!"); } - printConstant(CE->getOperand(1)); + printConstantWithCast(CE->getOperand(1), CE->getOpcode()); + if (NeedsClosingParens) + Out << "))"; Out << ')'; return; @@ -813,6 +820,71 @@ } } +// Some constant expressions need to be casted back to the original types +// because their operands were casted to the expected type. This function takes +// care of detecting that case and printing the cast for the ConstantExpr. +bool CWriter::printConstExprCast(const ConstantExpr* CE) { + bool Result = false; + const Type* Ty = CE->getOperand(0)->getType(); + switch (CE->getOpcode()) { + case Instruction::UDiv: Result = Ty->isSigned(); break; + case Instruction::SDiv: Result = Ty->isUnsigned(); break; + default: break; + } + if (Result) { + Out << "(("; + printType(Out, Ty); + Out << ")("; + } + return Result; +} + +// Print a constant assuming that it is the operand for a given Opcode. The +// opcodes that care about sign need to cast their operands to the expected +// type before the operation proceeds. This function does the casting. +void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) { + + // Extract the operand's type, we'll need it. + const Type* OpTy = CPV->getType(); + + // Indicate whether to do the cast or not. + bool shouldCast = false; + + // Based on the Opcode for which this Constant is being written, determine + // the new type to which the operand should be casted by setting the value + // of OpTy. If we change OpTy, also set shouldCast to true. + switch (Opcode) { + default: + // for most instructions, it doesn't matter + break; + case Instruction::UDiv: + // For UDiv to have unsigned operands + if (OpTy->isSigned()) { + OpTy = OpTy->getUnsignedVersion(); + shouldCast = true; + } + break; + case Instruction::SDiv: + if (OpTy->isUnsigned()) { + OpTy = OpTy->getSignedVersion(); + shouldCast = true; + } + break; + } + + // Write out the casted constnat if we should, otherwise just write the + // operand. + if (shouldCast) { + Out << "(("; + printType(Out, OpTy); + Out << ")"; + printConstant(CPV); + Out << ")"; + } else + writeOperand(CPV); + +} + void CWriter::writeOperandInternal(Value *Operand) { if (Instruction *I = dyn_cast<Instruction>(Operand)) if (isInlinableInst(*I) && !isDirectAlloca(I)) { @@ -841,6 +913,72 @@ Out << ')'; } +// Some instructions need to have their result value casted back to the +// original types because their operands were casted to the expected type. +// This function takes care of detecting that case and printing the cast +// for the Instruction. +bool CWriter::writeInstructionCast(const Instruction &I) { + bool Result = false; + const Type* Ty = I.getOperand(0)->getType(); + switch (I.getOpcode()) { + case Instruction::UDiv: Result = Ty->isSigned(); break; + case Instruction::SDiv: Result = Ty->isUnsigned(); break; + default: break; + } + if (Result) { + Out << "(("; + printType(Out, Ty); + Out << ")("; + } + return Result; +} + +// Write the operand with a cast to another type based on the Opcode being used. +// This will be used in cases where an instruction has specific type +// requirements (usually signedness) for its operands. +void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) { + + // Extract the operand's type, we'll need it. + const Type* OpTy = Operand->getType(); + + // Indicate whether to do the cast or not. + bool shouldCast = false; + + // Based on the Opcode for which this Operand is being written, determine + // the new type to which the operand should be casted by setting the value + // of OpTy. If we change OpTy, also set shouldCast to true. + switch (Opcode) { + default: + // for most instructions, it doesn't matter + break; + case Instruction::UDiv: + // For UDiv to have unsigned operands + if (OpTy->isSigned()) { + OpTy = OpTy->getUnsignedVersion(); + shouldCast = true; + } + break; + case Instruction::SDiv: + if (OpTy->isUnsigned()) { + OpTy = OpTy->getSignedVersion(); + shouldCast = true; + } + break; + } + + // Write out the casted operand if we should, otherwise just write the + // operand. + if (shouldCast) { + Out << "(("; + printType(Out, OpTy); + Out << ")"; + writeOperand(Operand); + Out << ")"; + } else + writeOperand(Operand); + +} + // generateCompilerSpecificCode - This is where we add conditional compilation // directives to cater to specific compilers as need be. // @@ -1651,7 +1789,15 @@ writeOperand(I.getOperand(1)); Out << ")"; } else { - writeOperand(I.getOperand(0)); + + // Write out the cast of the instruction's value back to the proper type + // if necessary. + bool NeedsClosingParens = writeInstructionCast(I); + + // Certain instructions require the operand to be forced to a specific type + // so we use writeOperandWithCast here instead of writeOperand. Similarly + // below for operand 1 + writeOperandWithCast(I.getOperand(0), I.getOpcode()); switch (I.getOpcode()) { case Instruction::Add: Out << " + "; break; @@ -1677,7 +1823,9 @@ default: std::cerr << "Invalid operator type!" << I; abort(); } - writeOperand(I.getOperand(1)); + writeOperandWithCast(I.getOperand(1), I.getOpcode()); + if (NeedsClosingParens) + Out << "))"; } if (needsCast) { _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits