mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-24 12:19:53 +00:00
Simplify writing floating types to assembly.
This removes previous special cases for each floating-point type in favour of a shared codepath. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172189 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
fc183ceae3
commit
5f2801bd65
@ -1746,90 +1746,48 @@ static void emitGlobalConstantStruct(const ConstantStruct *CS,
|
||||
|
||||
static void emitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace,
|
||||
AsmPrinter &AP) {
|
||||
if (CFP->getType()->isHalfTy()) {
|
||||
if (AP.isVerbose()) {
|
||||
SmallString<10> Str;
|
||||
CFP->getValueAPF().toString(Str);
|
||||
AP.OutStreamer.GetCommentOS() << "half " << Str << '\n';
|
||||
}
|
||||
uint64_t Val = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
|
||||
AP.OutStreamer.EmitIntValue(Val, 2, AddrSpace);
|
||||
return;
|
||||
}
|
||||
|
||||
if (CFP->getType()->isFloatTy()) {
|
||||
if (AP.isVerbose()) {
|
||||
float Val = CFP->getValueAPF().convertToFloat();
|
||||
uint64_t IntVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
|
||||
AP.OutStreamer.GetCommentOS() << "float " << Val << '\n'
|
||||
<< " (" << format("0x%x", IntVal) << ")\n";
|
||||
}
|
||||
uint64_t Val = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
|
||||
AP.OutStreamer.EmitIntValue(Val, 4, AddrSpace);
|
||||
return;
|
||||
}
|
||||
|
||||
// FP Constants are printed as integer constants to avoid losing
|
||||
// precision.
|
||||
if (CFP->getType()->isDoubleTy()) {
|
||||
if (AP.isVerbose()) {
|
||||
double Val = CFP->getValueAPF().convertToDouble();
|
||||
uint64_t IntVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
|
||||
AP.OutStreamer.GetCommentOS() << "double " << Val << '\n'
|
||||
<< " (" << format("0x%lx", IntVal) << ")\n";
|
||||
}
|
||||
|
||||
uint64_t Val = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
|
||||
AP.OutStreamer.EmitIntValue(Val, 8, AddrSpace);
|
||||
return;
|
||||
}
|
||||
|
||||
if (CFP->getType()->isX86_FP80Ty() || CFP->getType()->isFP128Ty()) {
|
||||
// all long double variants are printed as hex
|
||||
// API needed to prevent premature destruction
|
||||
APInt API = CFP->getValueAPF().bitcastToAPInt();
|
||||
const uint64_t *p = API.getRawData();
|
||||
if (AP.isVerbose()) {
|
||||
// Convert to double so we can print the approximate val as a comment.
|
||||
SmallString<8> StrVal;
|
||||
CFP->getValueAPF().toString(StrVal);
|
||||
|
||||
const char *TyNote = CFP->getType()->isFP128Ty() ? "fp128 " : "x86_fp80 ";
|
||||
AP.OutStreamer.GetCommentOS() << TyNote << StrVal << '\n';
|
||||
}
|
||||
|
||||
// The 80-bit type is made of a 64-bit and 16-bit value, the 128-bit has 2
|
||||
// 64-bit words.
|
||||
uint32_t TrailingSize = CFP->getType()->isFP128Ty() ? 8 : 2;
|
||||
|
||||
if (AP.TM.getDataLayout()->isBigEndian()) {
|
||||
AP.OutStreamer.EmitIntValue(p[1], TrailingSize, AddrSpace);
|
||||
AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace);
|
||||
} else {
|
||||
AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace);
|
||||
AP.OutStreamer.EmitIntValue(p[1], TrailingSize, AddrSpace);
|
||||
}
|
||||
|
||||
// Emit the tail padding for the long double.
|
||||
const DataLayout &TD = *AP.TM.getDataLayout();
|
||||
AP.OutStreamer.EmitZeros(TD.getTypeAllocSize(CFP->getType()) -
|
||||
TD.getTypeStoreSize(CFP->getType()), AddrSpace);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(CFP->getType()->isPPC_FP128Ty() &&
|
||||
"Floating point constant type not handled");
|
||||
// All long double variants are printed as hex
|
||||
// API needed to prevent premature destruction.
|
||||
APInt API = CFP->getValueAPF().bitcastToAPInt();
|
||||
const uint64_t *p = API.getRawData();
|
||||
if (AP.TM.getDataLayout()->isBigEndian()) {
|
||||
AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace);
|
||||
AP.OutStreamer.EmitIntValue(p[1], 8, AddrSpace);
|
||||
} else {
|
||||
AP.OutStreamer.EmitIntValue(p[1], 8, AddrSpace);
|
||||
AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace);
|
||||
|
||||
// First print a comment with what we think the original floating-point value
|
||||
// should have been.
|
||||
if (AP.isVerbose()) {
|
||||
SmallString<8> StrVal;
|
||||
CFP->getValueAPF().toString(StrVal);
|
||||
|
||||
CFP->getType()->print(AP.OutStreamer.GetCommentOS());
|
||||
AP.OutStreamer.GetCommentOS() << ' ' << StrVal << '\n';
|
||||
}
|
||||
|
||||
// Now iterate through the APInt chunks, emitting them in endian-correct
|
||||
// order, possibly with a smaller chunk at beginning/end (e.g. for x87 80-bit
|
||||
// floats).
|
||||
unsigned NumBytes = API.getBitWidth() / 8;
|
||||
unsigned TrailingBytes = NumBytes % sizeof(uint64_t);
|
||||
const uint64_t *p = API.getRawData();
|
||||
|
||||
// PPC's long double has odd notions of endianness compared to how LLVM
|
||||
// handles it: p[0] goes first for *big* endian on PPC.
|
||||
if (AP.TM.getDataLayout()->isBigEndian() != CFP->getType()->isPPC_FP128Ty()) {
|
||||
int Chunk = API.getNumWords() - 1;
|
||||
|
||||
if (TrailingBytes)
|
||||
AP.OutStreamer.EmitIntValue(p[Chunk--], TrailingBytes, AddrSpace);
|
||||
|
||||
for (; Chunk >= 0; --Chunk)
|
||||
AP.OutStreamer.EmitIntValue(p[Chunk], sizeof(uint64_t), AddrSpace);
|
||||
} else {
|
||||
unsigned Chunk;
|
||||
for (Chunk = 0; Chunk < NumBytes / sizeof(uint64_t); ++Chunk)
|
||||
AP.OutStreamer.EmitIntValue(p[Chunk], sizeof(uint64_t), AddrSpace);
|
||||
|
||||
if (TrailingBytes)
|
||||
AP.OutStreamer.EmitIntValue(p[Chunk], TrailingBytes, AddrSpace);
|
||||
}
|
||||
|
||||
// Emit the tail padding for the long double.
|
||||
const DataLayout &TD = *AP.TM.getDataLayout();
|
||||
AP.OutStreamer.EmitZeros(TD.getTypeAllocSize(CFP->getType()) -
|
||||
TD.getTypeStoreSize(CFP->getType()), AddrSpace);
|
||||
}
|
||||
|
||||
static void emitGlobalConstantLargeInt(const ConstantInt *CI,
|
||||
|
@ -1,10 +0,0 @@
|
||||
; RUN: llc -mtriple=arm-none-linux < %s | FileCheck --check-prefix=LITTLEENDIAN %s
|
||||
|
||||
@var = global fp128 0xL00000000000000008000000000000000
|
||||
|
||||
; CHECK-LITTLEENDIAN: var:
|
||||
; CHECK-LITTLEENDIAN-NEXT: .long 0 @ fp128 -0
|
||||
; CHECK-LITTLEENDIAN-NEXT: .long 0
|
||||
; CHECK-LITTLEENDIAN-NEXT: .long 0
|
||||
; CHECK-LITTLEENDIAN-NEXT: .long 2147483648
|
||||
|
34
test/CodeGen/PowerPC/float-asmprint.ll
Normal file
34
test/CodeGen/PowerPC/float-asmprint.ll
Normal file
@ -0,0 +1,34 @@
|
||||
; RUN: llc -mtriple=powerpc64-none-linux < %s | FileCheck %s
|
||||
|
||||
; Check that all current floating-point types are correctly emitted to assembly
|
||||
; on a big-endian target. x86_fp80 can't actually print for unrelated reasons,
|
||||
; but that's not really a problem.
|
||||
|
||||
@var128 = global fp128 0xL00000000000000008000000000000000, align 16
|
||||
@varppc128 = global ppc_fp128 0xM80000000000000000000000000000000, align 16
|
||||
@var64 = global double -0.0, align 8
|
||||
@var32 = global float -0.0, align 4
|
||||
@var16 = global half -0.0, align 2
|
||||
|
||||
; CHECK: var128:
|
||||
; CHECK-NEXT: .quad -9223372036854775808 # fp128 -0
|
||||
; CHECK-NEXT: .quad 0
|
||||
; CHECK-NEXT: .size
|
||||
|
||||
; CHECK: varppc128:
|
||||
; CHECK-NEXT: .quad -9223372036854775808 # ppc_fp128 -0
|
||||
; CHECK-NEXT: .quad 0
|
||||
; CHECK-NEXT: .size
|
||||
|
||||
; CHECK: var64:
|
||||
; CHECK-NEXT: .quad -9223372036854775808 # double -0
|
||||
; CHECK-NEXT: .size
|
||||
|
||||
; CHECK: var32:
|
||||
; CHECK-NEXT: .long 2147483648 # float -0
|
||||
; CHECK-NEXT: .size
|
||||
|
||||
; CHECK: var16:
|
||||
; CHECK-NEXT: .short 32768 # half -0
|
||||
; CHECK-NEXT: .size
|
||||
|
@ -1,8 +0,0 @@
|
||||
; RUN: llc -mtriple=powerpc64-none-linux < %s | FileCheck --check-prefix=BIGENDIAN %s
|
||||
|
||||
@var = global fp128 0xL00000000000000008000000000000000
|
||||
|
||||
; CHECK-BIGENDIAN: var:
|
||||
; CHECK-BIGENDIAN-NEXT: .quad -9223372036854775808 # fp128 -0
|
||||
; CHECK-BIGENDIAN-NEXT: .quad 0
|
||||
|
40
test/CodeGen/X86/float-asmprint.ll
Normal file
40
test/CodeGen/X86/float-asmprint.ll
Normal file
@ -0,0 +1,40 @@
|
||||
; RUN: llc -mtriple=x86_64-none-linux < %s | FileCheck %s
|
||||
|
||||
; Check that all current floating-point types are correctly emitted to assembly
|
||||
; on a little-endian target.
|
||||
|
||||
@var128 = global fp128 0xL00000000000000008000000000000000, align 16
|
||||
@varppc128 = global ppc_fp128 0xM80000000000000000000000000000000, align 16
|
||||
@var80 = global x86_fp80 0xK80000000000000000000, align 16
|
||||
@var64 = global double -0.0, align 8
|
||||
@var32 = global float -0.0, align 4
|
||||
@var16 = global half -0.0, align 2
|
||||
|
||||
; CHECK: var128:
|
||||
; CHECK-NEXT: .quad 0 # fp128 -0
|
||||
; CHECK-NEXT: .quad -9223372036854775808
|
||||
; CHECK-NEXT: .size
|
||||
|
||||
; CHECK: varppc128:
|
||||
; CHECK-NEXT: .quad 0 # ppc_fp128 -0
|
||||
; CHECK-NEXT: .quad -9223372036854775808
|
||||
; CHECK-NEXT: .size
|
||||
|
||||
; CHECK: var80:
|
||||
; CHECK-NEXT: .quad 0 # x86_fp80 -0
|
||||
; CHECK-NEXT: .short 32768
|
||||
; CHECK-NEXT: .zero 6
|
||||
; CHECK-NEXT: .size
|
||||
|
||||
; CHECK: var64:
|
||||
; CHECK-NEXT: .quad -9223372036854775808 # double -0
|
||||
; CHECK-NEXT: .size
|
||||
|
||||
; CHECK: var32:
|
||||
; CHECK-NEXT: .long 2147483648 # float -0
|
||||
; CHECK-NEXT: .size
|
||||
|
||||
; CHECK: var16:
|
||||
; CHECK-NEXT: .short 32768 # half -0
|
||||
; CHECK-NEXT: .size
|
||||
|
Loading…
Reference in New Issue
Block a user