module GHC.CmmToAsm.Ppr (
castFloatToWord8Array,
castDoubleToWord8Array,
floatToBytes,
doubleToBytes,
pprASCII,
pprString,
pprFileEmbed,
pprSectionHeader
)
where
import GHC.Prelude
import GHC.Utils.Asm
import GHC.Cmm.CLabel
import GHC.Cmm
import GHC.CmmToAsm.Config
import GHC.Data.FastString
import GHC.Utils.Outputable
import GHC.Platform
import qualified Data.Array.Unsafe as U ( castSTUArray )
import Data.Array.ST
import Control.Monad.ST
import Data.Word
import Data.Bits
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import GHC.Exts
import GHC.Word
castFloatToWord8Array :: STUArray s Int Float -> ST s (STUArray s Int Word8)
castFloatToWord8Array = U.castSTUArray
castDoubleToWord8Array :: STUArray s Int Double -> ST s (STUArray s Int Word8)
castDoubleToWord8Array = U.castSTUArray
floatToBytes :: Float -> [Int]
floatToBytes f
= runST (do
arr <- newArray_ ((0::Int),3)
writeArray arr 0 f
arr <- castFloatToWord8Array arr
i0 <- readArray arr 0
i1 <- readArray arr 1
i2 <- readArray arr 2
i3 <- readArray arr 3
return (map fromIntegral [i0,i1,i2,i3])
)
doubleToBytes :: Double -> [Int]
doubleToBytes d
= runST (do
arr <- newArray_ ((0::Int),7)
writeArray arr 0 d
arr <- castDoubleToWord8Array arr
i0 <- readArray arr 0
i1 <- readArray arr 1
i2 <- readArray arr 2
i3 <- readArray arr 3
i4 <- readArray arr 4
i5 <- readArray arr 5
i6 <- readArray arr 6
i7 <- readArray arr 7
return (map fromIntegral [i0,i1,i2,i3,i4,i5,i6,i7])
)
pprASCII :: ByteString -> SDoc
pprASCII str
= text $ BS.foldr (\w s -> do1 w ++ s) "" str
where
do1 :: Word8 -> String
do1 w | 0x09 == w = "\\t"
| 0x0A == w = "\\n"
| 0x22 == w = "\\\""
| 0x5C == w = "\\\\"
| w >= 0x20 && w <= 0x7E = [chr' w]
| otherwise = '\\' : octal w
chr' :: Word8 -> Char
chr' (W8# w#) = C# (chr# (word2Int# w#))
octal :: Word8 -> String
octal w = [ chr' (ord0 + (w `unsafeShiftR` 6) .&. 0x07)
, chr' (ord0 + (w `unsafeShiftR` 3) .&. 0x07)
, chr' (ord0 + w .&. 0x07)
]
ord0 = 0x30
pprString :: ByteString -> SDoc
pprString bs = text "\t.string " <> doubleQuotes (pprASCII bs)
pprFileEmbed :: FilePath -> SDoc
pprFileEmbed path
= text "\t.incbin "
<> pprFilePathString path
<> text "\n\t.byte 0"
pprSectionHeader :: NCGConfig -> Section -> SDoc
pprSectionHeader config (Section t suffix) =
case platformOS (ncgPlatform config) of
OSAIX -> pprXcoffSectionHeader t
OSDarwin -> pprDarwinSectionHeader t
OSMinGW32 -> pprGNUSectionHeader config (char '$') t suffix
_ -> pprGNUSectionHeader config (char '.') t suffix
pprGNUSectionHeader :: NCGConfig -> SDoc -> SectionType -> CLabel -> SDoc
pprGNUSectionHeader config sep t suffix =
text ".section " <> ptext header <> subsection <> flags
where
platform = ncgPlatform config
splitSections = ncgSplitSections config
subsection
| splitSections = sep <> ppr suffix
| otherwise = empty
header = case t of
Text -> sLit ".text"
Data -> sLit ".data"
ReadOnlyData | OSMinGW32 <- platformOS platform
-> sLit ".rdata"
| otherwise -> sLit ".rodata"
RelocatableReadOnlyData | OSMinGW32 <- platformOS platform
-> sLit ".rdata$rel.ro"
| otherwise -> sLit ".data.rel.ro"
UninitialisedData -> sLit ".bss"
ReadOnlyData16 | OSMinGW32 <- platformOS platform
-> sLit ".rdata$cst16"
| otherwise -> sLit ".rodata.cst16"
CString
| OSMinGW32 <- platformOS platform
-> sLit ".rdata"
| otherwise -> sLit ".rodata.str"
OtherSection _ ->
panic "PprBase.pprGNUSectionHeader: unknown section type"
flags = case t of
CString
| OSMinGW32 <- platformOS platform
-> empty
| otherwise -> text ",\"aMS\"," <> sectionType platform "progbits" <> text ",1"
_ -> empty
pprXcoffSectionHeader :: SectionType -> SDoc
pprXcoffSectionHeader t = text $ case t of
Text -> ".csect .text[PR]"
Data -> ".csect .data[RW]"
ReadOnlyData -> ".csect .text[PR] # ReadOnlyData"
RelocatableReadOnlyData -> ".csect .text[PR] # RelocatableReadOnlyData"
ReadOnlyData16 -> ".csect .text[PR] # ReadOnlyData16"
CString -> ".csect .text[PR] # CString"
UninitialisedData -> ".csect .data[BS]"
OtherSection _ ->
panic "PprBase.pprXcoffSectionHeader: unknown section type"
pprDarwinSectionHeader :: SectionType -> SDoc
pprDarwinSectionHeader t =
ptext $ case t of
Text -> sLit ".text"
Data -> sLit ".data"
ReadOnlyData -> sLit ".const"
RelocatableReadOnlyData -> sLit ".const_data"
UninitialisedData -> sLit ".data"
ReadOnlyData16 -> sLit ".const"
CString -> sLit ".section\t__TEXT,__cstring,cstring_literals"
OtherSection _ ->
panic "PprBase.pprDarwinSectionHeader: unknown section type"