Implement correct bitcast of int<->float and long<->double by using a

union to perform the bitcast.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@32444 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Reid Spencer 2006-12-11 20:39:15 +00:00
parent 13acce3ef0
commit 555a0b189c
2 changed files with 116 additions and 28 deletions

View File

@ -169,7 +169,7 @@ namespace {
// Must not be used in inline asm // Must not be used in inline asm
if (I.hasOneUse() && isInlineAsm(*I.use_back())) return false; if (I.hasOneUse() && isInlineAsm(*I.use_back())) return false;
// Only inline instruction it it's use is in the same BB as the inst. // Only inline instruction it if it's use is in the same BB as the inst.
return I.getParent() == cast<Instruction>(I.use_back())->getParent(); return I.getParent() == cast<Instruction>(I.use_back())->getParent();
} }
@ -1508,6 +1508,16 @@ void CWriter::printFloatingPointConstants(Function &F) {
/// type name is found, emit its declaration... /// type name is found, emit its declaration...
/// ///
void CWriter::printModuleTypes(const SymbolTable &ST) { void CWriter::printModuleTypes(const SymbolTable &ST) {
Out << "/* Helper union for bitcasts */\n";
Out << "typedef union {\n";
Out << " unsigned int UInt;\n";
Out << " signed int SInt;\n";
Out << " unsigned long ULong;\n";
Out << " signed long SLong;\n";
Out << " float Float;\n";
Out << " double Double;\n";
Out << "} llvmBitCastUnion;\n";
// We are only interested in the type plane of the symbol table. // We are only interested in the type plane of the symbol table.
SymbolTable::type_const_iterator I = ST.type_begin(); SymbolTable::type_const_iterator I = ST.type_begin();
SymbolTable::type_const_iterator End = ST.type_end(); SymbolTable::type_const_iterator End = ST.type_end();
@ -1704,6 +1714,15 @@ void CWriter::printFunction(Function &F) {
Out << ";\n"; Out << ";\n";
} }
PrintedVar = true; PrintedVar = true;
} else if (isa<BitCastInst>(*I) &&
((I->getType()->isFloatingPoint() &&
I->getOperand(0)->getType()->isInteger()) ||
(I->getType()->isInteger() &&
I->getOperand(0)->getType()->isFloatingPoint()))) {
// We need a temporary for the BitCast to use so it can pluck a
// value out of a union to do the BitCast.
Out << " llvmBitCastUnion " << Mang->getValueName(&*I)
<< "__BITCAST_TEMPORARY;\n";
} }
if (PrintedVar) if (PrintedVar)
@ -1986,23 +2005,48 @@ void CWriter::visitBinaryOperator(Instruction &I) {
} }
} }
static const char * getFloatBitCastField(const Type *Ty) {
switch (Ty->getTypeID()) {
default: assert(0 && "Invalid Type");
case Type::FloatTyID: return "Float";
case Type::UIntTyID: return "UInt";
case Type::IntTyID: return "SInt";
case Type::DoubleTyID:return "Double";
case Type::ULongTyID: return "ULong";
case Type::LongTyID: return "SLong";
}
}
void CWriter::visitCastInst(CastInst &I) { void CWriter::visitCastInst(CastInst &I) {
const Type *DstTy = I.getType(); const Type *DstTy = I.getType();
const Type *SrcTy = I.getOperand(0)->getType(); const Type *SrcTy = I.getOperand(0)->getType();
Out << '('; Out << '(';
printCast(I.getOpcode(), SrcTy, DstTy); if (isa<BitCastInst>(I) &&
if (I.getOpcode() == Instruction::SExt && SrcTy == Type::BoolTy) { ((I.getType()->isFloatingPoint() &&
// Make sure we really get a sext from bool by subtracing the bool from 0 I.getOperand(0)->getType()->isInteger()) ||
Out << "0-"; (I.getType()->isInteger() &&
} I.getOperand(0)->getType()->isFloatingPoint()))) {
writeOperand(I.getOperand(0)); // These int<->float and long<->double casts need to be handled specially
if (DstTy == Type::BoolTy && Out << Mang->getValueName(&I) << "__BITCAST_TEMPORARY."
(I.getOpcode() == Instruction::Trunc || << getFloatBitCastField(I.getOperand(0)->getType()) << " = ";
I.getOpcode() == Instruction::FPToUI || writeOperand(I.getOperand(0));
I.getOpcode() == Instruction::FPToSI || Out << ", " << Mang->getValueName(&I) << "__BITCAST_TEMPORARY."
I.getOpcode() == Instruction::PtrToInt)) { << getFloatBitCastField(I.getType());
// Make sure we really get a trunc to bool by anding the operand with 1 } else {
Out << "&1u"; printCast(I.getOpcode(), SrcTy, DstTy);
if (I.getOpcode() == Instruction::SExt && SrcTy == Type::BoolTy) {
// Make sure we really get a sext from bool by subtracing the bool from 0
Out << "0-";
}
writeOperand(I.getOperand(0));
if (DstTy == Type::BoolTy &&
(I.getOpcode() == Instruction::Trunc ||
I.getOpcode() == Instruction::FPToUI ||
I.getOpcode() == Instruction::FPToSI ||
I.getOpcode() == Instruction::PtrToInt)) {
// Make sure we really get a trunc to bool by anding the operand with 1
Out << "&1u";
}
} }
Out << ')'; Out << ')';
} }

View File

@ -169,7 +169,7 @@ namespace {
// Must not be used in inline asm // Must not be used in inline asm
if (I.hasOneUse() && isInlineAsm(*I.use_back())) return false; if (I.hasOneUse() && isInlineAsm(*I.use_back())) return false;
// Only inline instruction it it's use is in the same BB as the inst. // Only inline instruction it if it's use is in the same BB as the inst.
return I.getParent() == cast<Instruction>(I.use_back())->getParent(); return I.getParent() == cast<Instruction>(I.use_back())->getParent();
} }
@ -1508,6 +1508,16 @@ void CWriter::printFloatingPointConstants(Function &F) {
/// type name is found, emit its declaration... /// type name is found, emit its declaration...
/// ///
void CWriter::printModuleTypes(const SymbolTable &ST) { void CWriter::printModuleTypes(const SymbolTable &ST) {
Out << "/* Helper union for bitcasts */\n";
Out << "typedef union {\n";
Out << " unsigned int UInt;\n";
Out << " signed int SInt;\n";
Out << " unsigned long ULong;\n";
Out << " signed long SLong;\n";
Out << " float Float;\n";
Out << " double Double;\n";
Out << "} llvmBitCastUnion;\n";
// We are only interested in the type plane of the symbol table. // We are only interested in the type plane of the symbol table.
SymbolTable::type_const_iterator I = ST.type_begin(); SymbolTable::type_const_iterator I = ST.type_begin();
SymbolTable::type_const_iterator End = ST.type_end(); SymbolTable::type_const_iterator End = ST.type_end();
@ -1704,6 +1714,15 @@ void CWriter::printFunction(Function &F) {
Out << ";\n"; Out << ";\n";
} }
PrintedVar = true; PrintedVar = true;
} else if (isa<BitCastInst>(*I) &&
((I->getType()->isFloatingPoint() &&
I->getOperand(0)->getType()->isInteger()) ||
(I->getType()->isInteger() &&
I->getOperand(0)->getType()->isFloatingPoint()))) {
// We need a temporary for the BitCast to use so it can pluck a
// value out of a union to do the BitCast.
Out << " llvmBitCastUnion " << Mang->getValueName(&*I)
<< "__BITCAST_TEMPORARY;\n";
} }
if (PrintedVar) if (PrintedVar)
@ -1986,23 +2005,48 @@ void CWriter::visitBinaryOperator(Instruction &I) {
} }
} }
static const char * getFloatBitCastField(const Type *Ty) {
switch (Ty->getTypeID()) {
default: assert(0 && "Invalid Type");
case Type::FloatTyID: return "Float";
case Type::UIntTyID: return "UInt";
case Type::IntTyID: return "SInt";
case Type::DoubleTyID:return "Double";
case Type::ULongTyID: return "ULong";
case Type::LongTyID: return "SLong";
}
}
void CWriter::visitCastInst(CastInst &I) { void CWriter::visitCastInst(CastInst &I) {
const Type *DstTy = I.getType(); const Type *DstTy = I.getType();
const Type *SrcTy = I.getOperand(0)->getType(); const Type *SrcTy = I.getOperand(0)->getType();
Out << '('; Out << '(';
printCast(I.getOpcode(), SrcTy, DstTy); if (isa<BitCastInst>(I) &&
if (I.getOpcode() == Instruction::SExt && SrcTy == Type::BoolTy) { ((I.getType()->isFloatingPoint() &&
// Make sure we really get a sext from bool by subtracing the bool from 0 I.getOperand(0)->getType()->isInteger()) ||
Out << "0-"; (I.getType()->isInteger() &&
} I.getOperand(0)->getType()->isFloatingPoint()))) {
writeOperand(I.getOperand(0)); // These int<->float and long<->double casts need to be handled specially
if (DstTy == Type::BoolTy && Out << Mang->getValueName(&I) << "__BITCAST_TEMPORARY."
(I.getOpcode() == Instruction::Trunc || << getFloatBitCastField(I.getOperand(0)->getType()) << " = ";
I.getOpcode() == Instruction::FPToUI || writeOperand(I.getOperand(0));
I.getOpcode() == Instruction::FPToSI || Out << ", " << Mang->getValueName(&I) << "__BITCAST_TEMPORARY."
I.getOpcode() == Instruction::PtrToInt)) { << getFloatBitCastField(I.getType());
// Make sure we really get a trunc to bool by anding the operand with 1 } else {
Out << "&1u"; printCast(I.getOpcode(), SrcTy, DstTy);
if (I.getOpcode() == Instruction::SExt && SrcTy == Type::BoolTy) {
// Make sure we really get a sext from bool by subtracing the bool from 0
Out << "0-";
}
writeOperand(I.getOperand(0));
if (DstTy == Type::BoolTy &&
(I.getOpcode() == Instruction::Trunc ||
I.getOpcode() == Instruction::FPToUI ||
I.getOpcode() == Instruction::FPToSI ||
I.getOpcode() == Instruction::PtrToInt)) {
// Make sure we really get a trunc to bool by anding the operand with 1
Out << "&1u";
}
} }
Out << ')'; Out << ')';
} }