[GHC] #5218: Add unpackCStringLen# to create Strings from string literals
GHC
cvs-ghc at haskell.org
Fri Jun 10 11:58:30 CEST 2011
#5218: Add unpackCStringLen# to create Strings from string literals
---------------------------------+------------------------------------------
Reporter: tibbe | Owner:
Type: feature request | Status: new
Priority: high | Milestone: 7.4.1
Component: Compiler | Version: 7.0.3
Keywords: | Testcase:
Blockedby: | Difficulty:
Os: Unknown/Multiple | Blocking:
Architecture: Unknown/Multiple | Failure: None/Unknown
---------------------------------+------------------------------------------
Comment(by simonmar):
Simon and I discussed this just now and found two further problems in
addition to the extra runtime length operation described above.
'''1. The RULES in `ByteString` for optimising literal strings currently
do not work'''
e.g. try
{{{
{-# LANGUAGE OverloadedStrings #-}
module Foo where
import Data.ByteString.Char8
foo = "abc"
}}}
the generated code does the translation to/from `String` at runtime.
Presumably this broke at some point, possibly due to things being inlined
at the wrong time and/or let-floating.
'''2. The RULES in `ByteString` never worked for non-ASCII strings'''
This is because non-ASCII strings are UTF-8-encoded by GHC and wrapped in
`unpackCStringUtf8`, not `unpackCString`, so the RULEs don't apply.
----------
We have two solutions.
'''1. Use quasi-quoting to declare `ByteString` literals.'''
You would write something like
{{{
foo :: ByteString
foo = [bytes| ffa3c9db77 ]
}}}
and the code for `bytes` would translate this directly into a call to
`unsafePackAddress` passing a primitive literal string (`HsStringPrim`,
aka `"..."#`). Note that primitive literal strings are not UTF-8-encoded
by GHC, they are just 8-bit stripped (this happens in the lexer, of all
places).
This would be more convenient for encoding static data into the program
through `ByteString` literals.
'''2. Fix the RULES for `ByteString` literals.'''
Here's one way we could fix all the problems described above. It's a bit
tricky and requires changes in various places.
First, somewhere in `base` or `ghc-prim` we have
{{{
newtype String8 = String8 String
string8 :: String -> String8
{-# INLINE [0] string8 #-}
string8 = String8
unpackCString :: Addr# -> String
unpackCStringUtf8 :: Addr# -> String
unpackCString8Len :: Addr# -> Int# -> String8
}}}
Next, GHC internally has RULEs that convert
{{{
string8 (unpackCStringUtf8 <utf8stringlit#>)
===> unpackCString8Len <stringlit#> <len#>
string8 (unpackCString <asciistringlit#>)
===> unpackCString8Len <asciistringlit#> <len#>
}}}
where `<stringlit#>` is made by decoding `<utf8stringlit#>` and stripping
out bits 8 and above from each character.
Then in `Data.ByteString.Char8` we have:
{{{
module Data.ByteString.Char8 where
packAddressLen :: Addr# -> Int# -> ByteString
pack8 :: String8 -> ByteString
instance IsString ByteString where
fromString = pack . string8
{-# RULES "pack8/unpackCString8"
pack8 (unpackCString8 addr len) = packAddressLen addr len
#-}
}}}
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/5218#comment:3>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the Glasgow-haskell-bugs
mailing list