compiler: test float to int conversions and fix upper-bound calculation
Этот коммит содержится в:
родитель
a90865506d
коммит
a5cf704d83
6 изменённых файлов: 144 добавлений и 7 удалений
|
@ -2569,7 +2569,7 @@ func (b *builder) createConvert(typeFrom, typeTo types.Type, value llvm.Value, p
|
|||
maxFloat := float64(max)
|
||||
if bits.Len64(max) > significandBits {
|
||||
// Round the max down to fit within the significand.
|
||||
maxFloat = float64(max & ^uint64(0) << uint(bits.Len64(max)-significandBits))
|
||||
maxFloat = float64(max & (^uint64(0) << uint(bits.Len64(max)-significandBits)))
|
||||
}
|
||||
|
||||
// Check if the value is in-bounds (0 <= value <= max).
|
||||
|
@ -2598,7 +2598,7 @@ func (b *builder) createConvert(typeFrom, typeTo types.Type, value llvm.Value, p
|
|||
maxFloat := float64(max)
|
||||
if bits.Len64(max) > significandBits {
|
||||
// Round the max down to fit within the significand.
|
||||
maxFloat = float64(max & ^uint64(0) << uint(bits.Len64(max)-significandBits))
|
||||
maxFloat = float64(max & (^uint64(0) << uint(bits.Len64(max)-significandBits)))
|
||||
}
|
||||
|
||||
// Check if the value is in-bounds (min <= value <= max).
|
||||
|
@ -2609,10 +2609,17 @@ func (b *builder) createConvert(typeFrom, typeTo types.Type, value llvm.Value, p
|
|||
// Assuming that the value is out-of-bounds, select a saturated value.
|
||||
saturated := b.CreateSelect(aboveMin,
|
||||
llvm.ConstInt(llvmTypeTo, max, false), // value > max
|
||||
llvm.ConstInt(llvmTypeTo, min, false), // value < min (or NaN)
|
||||
llvm.ConstInt(llvmTypeTo, min, false), // value < min
|
||||
"saturated",
|
||||
)
|
||||
|
||||
// Map NaN to 0.
|
||||
saturated = b.CreateSelect(b.CreateFCmp(llvm.FloatUNO, value, value, "isnan"),
|
||||
llvm.ConstNull(llvmTypeTo),
|
||||
saturated,
|
||||
"remapped",
|
||||
)
|
||||
|
||||
// Do a normal conversion.
|
||||
normal := b.CreateFPToSI(value, llvmTypeTo, "normal")
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ func TestCompiler(t *testing.T) {
|
|||
"basic.go",
|
||||
"pointer.go",
|
||||
"slice.go",
|
||||
"float.go",
|
||||
}
|
||||
|
||||
for _, testCase := range tests {
|
||||
|
|
39
compiler/testdata/float.go
предоставленный
Обычный файл
39
compiler/testdata/float.go
предоставленный
Обычный файл
|
@ -0,0 +1,39 @@
|
|||
package main
|
||||
|
||||
// Test converting floats to ints.
|
||||
|
||||
func f32tou32(v float32) uint32 {
|
||||
return uint32(v)
|
||||
}
|
||||
|
||||
func maxu32f() float32 {
|
||||
return float32(^uint32(0))
|
||||
}
|
||||
|
||||
func maxu32tof32() uint32 {
|
||||
f := float32(^uint32(0))
|
||||
return uint32(f)
|
||||
}
|
||||
|
||||
func inftoi32() (uint32, uint32, int32, int32) {
|
||||
inf := 1.0
|
||||
inf /= 0.0
|
||||
|
||||
return uint32(inf), uint32(-inf), int32(inf), int32(-inf)
|
||||
}
|
||||
|
||||
func u32tof32tou32(v uint32) uint32 {
|
||||
return uint32(float32(v))
|
||||
}
|
||||
|
||||
func f32tou32tof32(v float32) float32 {
|
||||
return float32(uint32(v))
|
||||
}
|
||||
|
||||
func f32tou8(v float32) uint8 {
|
||||
return uint8(v)
|
||||
}
|
||||
|
||||
func f32toi8(v float32) int8 {
|
||||
return int8(v)
|
||||
}
|
80
compiler/testdata/float.ll
предоставленный
Обычный файл
80
compiler/testdata/float.ll
предоставленный
Обычный файл
|
@ -0,0 +1,80 @@
|
|||
; ModuleID = 'float.go'
|
||||
source_filename = "float.go"
|
||||
target datalayout = "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-f80:32-n8:16:32-S128"
|
||||
target triple = "i686--linux"
|
||||
|
||||
define internal void @main.init(i8* %context, i8* %parentHandle) unnamed_addr {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
define internal i32 @main.f32tou32(float %v, i8* %context, i8* %parentHandle) unnamed_addr {
|
||||
entry:
|
||||
%positive = fcmp oge float %v, 0.000000e+00
|
||||
%withinmax = fcmp ole float %v, 0x41EFFFFFC0000000
|
||||
%inbounds = and i1 %positive, %withinmax
|
||||
%saturated = sext i1 %positive to i32
|
||||
%normal = fptoui float %v to i32
|
||||
%0 = select i1 %inbounds, i32 %normal, i32 %saturated
|
||||
ret i32 %0
|
||||
}
|
||||
|
||||
define internal float @main.maxu32f(i8* %context, i8* %parentHandle) unnamed_addr {
|
||||
entry:
|
||||
ret float 0x41F0000000000000
|
||||
}
|
||||
|
||||
define internal i32 @main.maxu32tof32(i8* %context, i8* %parentHandle) unnamed_addr {
|
||||
entry:
|
||||
ret i32 -1
|
||||
}
|
||||
|
||||
define internal { i32, i32, i32, i32 } @main.inftoi32(i8* %context, i8* %parentHandle) unnamed_addr {
|
||||
entry:
|
||||
ret { i32, i32, i32, i32 } { i32 -1, i32 0, i32 2147483647, i32 -2147483648 }
|
||||
}
|
||||
|
||||
define internal i32 @main.u32tof32tou32(i32 %v, i8* %context, i8* %parentHandle) unnamed_addr {
|
||||
entry:
|
||||
%0 = uitofp i32 %v to float
|
||||
%withinmax = fcmp ole float %0, 0x41EFFFFFC0000000
|
||||
%normal = fptoui float %0 to i32
|
||||
%1 = select i1 %withinmax, i32 %normal, i32 -1
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
define internal float @main.f32tou32tof32(float %v, i8* %context, i8* %parentHandle) unnamed_addr {
|
||||
entry:
|
||||
%positive = fcmp oge float %v, 0.000000e+00
|
||||
%withinmax = fcmp ole float %v, 0x41EFFFFFC0000000
|
||||
%inbounds = and i1 %positive, %withinmax
|
||||
%saturated = sext i1 %positive to i32
|
||||
%normal = fptoui float %v to i32
|
||||
%0 = select i1 %inbounds, i32 %normal, i32 %saturated
|
||||
%1 = uitofp i32 %0 to float
|
||||
ret float %1
|
||||
}
|
||||
|
||||
define internal i8 @main.f32tou8(float %v, i8* %context, i8* %parentHandle) unnamed_addr {
|
||||
entry:
|
||||
%positive = fcmp oge float %v, 0.000000e+00
|
||||
%withinmax = fcmp ole float %v, 2.550000e+02
|
||||
%inbounds = and i1 %positive, %withinmax
|
||||
%saturated = sext i1 %positive to i8
|
||||
%normal = fptoui float %v to i8
|
||||
%0 = select i1 %inbounds, i8 %normal, i8 %saturated
|
||||
ret i8 %0
|
||||
}
|
||||
|
||||
define internal i8 @main.f32toi8(float %v, i8* %context, i8* %parentHandle) unnamed_addr {
|
||||
entry:
|
||||
%abovemin = fcmp oge float %v, -1.280000e+02
|
||||
%belowmax = fcmp ole float %v, 1.270000e+02
|
||||
%inbounds = and i1 %abovemin, %belowmax
|
||||
%saturated = select i1 %abovemin, i8 127, i8 -128
|
||||
%isnan = fcmp uno float %v, 0.000000e+00
|
||||
%remapped = select i1 %isnan, i8 0, i8 %saturated
|
||||
%normal = fptosi float %v to i8
|
||||
%0 = select i1 %inbounds, i8 %normal, i8 %remapped
|
||||
ret i8 %0
|
||||
}
|
15
testdata/float.go
предоставленный
15
testdata/float.go
предоставленный
|
@ -29,12 +29,21 @@ func main() {
|
|||
var f2 float32 = 5.7
|
||||
var f3 float32 = -2.3
|
||||
var f4 float32 = -11.8
|
||||
println(int32(f1), int32(f2), int32(f3), int32(f4))
|
||||
|
||||
// float -> int saturating behavior
|
||||
var f5 float32 = -1
|
||||
var f6 float32 = 256
|
||||
var f7 float32 = -129
|
||||
var f8 float32 = 0
|
||||
f8 /= 0
|
||||
println(int32(f1), int32(f2), int32(f3), int32(f4), uint8(f5), uint8(f6), int8(f7), int8(f6), uint8(f8), int8(f8))
|
||||
f8 := float32(^uint32(0))
|
||||
f9 := float32(int32(-2147483648))
|
||||
f10 := float32(int32(2147483647))
|
||||
var inf float32 = 1
|
||||
inf /= 0
|
||||
var nan float32 = 0
|
||||
nan /= 0
|
||||
println(uint8(f5), uint8(f6), int8(f7), int8(f6), uint32(f8), int32(f9), int32(f10),
|
||||
uint8(inf), uint8(-inf), int8(inf), int8(-inf), uint8(nan), int64(nan))
|
||||
|
||||
// int -> float
|
||||
var i1 int32 = 53
|
||||
|
|
3
testdata/float.txt
предоставленный
3
testdata/float.txt
предоставленный
|
@ -11,7 +11,8 @@
|
|||
+3.333333e-001
|
||||
+6.666667e-001
|
||||
+6.666667e-001
|
||||
3 5 -2 -11 0 255 -128 127 0 -128
|
||||
3 5 -2 -11
|
||||
0 255 -128 127 4294967295 -2147483648 2147483647 255 0 127 -128 0 0
|
||||
+5.300000e+001 -8.000000e+000 +2.000000e+001
|
||||
(+6.666667e-001+1.200000e+000i)
|
||||
+6.666667e-001
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче