Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Alex D
GHC
Commits
25f8d040
Commit
25f8d040
authored
Jan 16, 2013
by
dterei
Browse files
Fix floating point constants in LLVM backend (#7600).
parent
5cca0b44
Changes
1
Hide whitespace changes
Inline
Side-by-side
compiler/llvmGen/Llvm/Types.hs
View file @
25f8d040
...
...
@@ -18,6 +18,8 @@ import Unique
-- from NCG
import
PprBase
import
GHC.Float
-- -----------------------------------------------------------------------------
-- * LLVM Basic Types and Variables
--
...
...
@@ -227,7 +229,8 @@ getLit :: LlvmLit -> String
getLit
(
LMIntLit
i
(
LMInt
32
))
=
show
(
fromInteger
i
::
Int32
)
getLit
(
LMIntLit
i
(
LMInt
64
))
=
show
(
fromInteger
i
::
Int64
)
getLit
(
LMIntLit
i
_
)
=
show
(
fromInteger
i
::
Int
)
getLit
(
LMFloatLit
r
LMFloat
)
=
fToStr
$
realToFrac
r
-- See Note [LLVM Float Types].
getLit
(
LMFloatLit
r
LMFloat
)
=
(
dToStr
.
widenFp
.
narrowFp
)
r
getLit
(
LMFloatLit
r
LMDouble
)
=
dToStr
r
getLit
f
@
(
LMFloatLit
_
_
)
=
error
$
"Can't print this float literal!"
++
show
f
getLit
(
LMNullLit
_
)
=
"null"
...
...
@@ -792,6 +795,8 @@ instance Show LlvmCastOp where
-- | Convert a Haskell Double to an LLVM hex encoded floating point form. In
-- Llvm float literals can be printed in a big-endian hexadecimal format,
-- regardless of underlying architecture.
--
-- See Note [LLVM Float Types].
dToStr
::
Double
->
String
dToStr
d
=
let
bs
=
doubleToBytes
d
...
...
@@ -804,13 +809,30 @@ dToStr d
str
=
map
toUpper
$
concat
.
fixEndian
.
(
map
hex
)
$
bs
in
"0x"
++
str
-- | Convert a Haskell Float to an LLVM hex encoded floating point form.
-- LLVM uses the same encoding for both floats and doubles (16 digit hex
-- string) but floats must have the last half all zeroes so it can fit into
-- a float size type.
{-# NOINLINE fToStr #-}
fToStr
::
Float
->
String
fToStr
=
(
dToStr
.
realToFrac
)
-- Note [LLVM Float Types]
-- ~~~~~~~~~~~~~~~~~~~~~~~
-- We use 'dToStr' for both printing Float and Double floating point types. This is
-- as LLVM expects all floating point constants (single & double) to be in IEEE
-- 754 Double precision format. However, for single precision numbers (Float)
-- they should be *representable* in IEEE 754 Single precision format. So the
-- easiest way to do this is to narrow and widen again.
-- (i.e., Double -> Float -> Double). We must be careful doing this that GHC
-- doesn't optimize that away.
-- Note [narrowFp & widenFp]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~
-- NOTE: we use float2Double & co directly as GHC likes to optimize away
-- successive calls of 'realToFrac', defeating the narrowing. (Bug #7600).
-- 'realToFrac' has inconsistent behaviour with optimisation as well that can
-- also cause issues, these methods don't.
narrowFp
::
Double
->
Float
{-# NOINLINE narrowFp #-}
narrowFp
=
double2Float
widenFp
::
Float
->
Double
{-# NOINLINE widenFp #-}
widenFp
=
float2Double
-- | Reverse or leave byte data alone to fix endianness on this target.
fixEndian
::
[
a
]
->
[
a
]
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment