use __magic_inline hack & stdcall for toolbox calls

This commit is contained in:
Wolfgang Thaller 2012-04-15 03:34:57 +02:00
parent 390818e425
commit 027af8eb8a

View File

@ -7,7 +7,7 @@ import System.Directory
import System.FilePath import System.FilePath
import Control.Monad(guard) import Control.Monad(guard)
import Data.List(isSuffixOf) import Data.List(isSuffixOf)
import qualified System.IO.Error(try) import qualified Control.Exception
import System.IO import System.IO
import qualified Text.PrettyPrint.HughesPJ as PP import qualified Text.PrettyPrint.HughesPJ as PP
import Text.PrettyPrint.HughesPJ((<+>),(<>),($$),($+$)) import Text.PrettyPrint.HughesPJ((<+>),(<>),($$),($+$))
@ -20,7 +20,7 @@ import System.Environment(getArgs)
data Item = CharItem Char data Item = CharItem Char
| IgnoredItem | IgnoredItem
| FunctionItem String String [String] [Integer] (Maybe ParameterRegs) | FunctionItem String String [String] [String] [Integer] (Maybe ParameterRegs)
| PragmaParameterItem String ParameterRegs | PragmaParameterItem String ParameterRegs
deriving(Show) deriving(Show)
@ -55,7 +55,11 @@ externApiDeclaration = do
guard ("WORDINLINE" `isSuffixOf` inlinekey) guard ("WORDINLINE" `isSuffixOf` inlinekey)
parens tp (commaSep tp hexword) parens tp (commaSep tp hexword)
semi tp semi tp
return $ FunctionItem rettype name (if arguments == ["void"] then [] else arguments) inlines Nothing let arguments' | arguments == ["void"] = []
| otherwise = arguments
argumentNames = map (trim . reverse . takeWhile isAlphaNum . reverse . trim) arguments'
argumentTypes = map (trim . reverse . dropWhile isAlphaNum . reverse . trim) arguments'
return $ FunctionItem rettype name argumentTypes argumentNames inlines Nothing
pragmaParameter = do pragmaParameter = do
reservedOp tp "#" reservedOp tp "#"
@ -90,11 +94,49 @@ classifyType tm t = Map.lookup t tm
hexword = integer tp hexword = integer tp
outputItem typeMap (CharItem c) = [c] outputItem typeMap (CharItem c) = [c]
-- outputItem (FunctionItem rettype name arguments words) = "<fun>" -- outputItem (FunctionItem rettype name argumentTypes argumentNames words) = "<fun>"
outputItem typeMap (FunctionItem rettype name arguments words mbParamRegs) =
outputItem typeMap (FunctionItem rettype name argumentTypes argumentNames words Nothing)
| True, not (null words), Just retcat <- classifyType typeMap rettype
= let
helper = PP.text "__magic_inline_" <> PP.text name
magic = PP.text "__magic_inline_" <> PP.hcat (PP.punctuate (PP.char '_') (map (PP.text . hexword) words'))
hexword w = replicate (4 - length s) '0' ++ s where s = showHex w ""
magicArgTypes = case retcat of
ByteType -> reverse $ "char" : argumentTypes
WordType -> reverse $ "short" : argumentTypes
LongType -> reverse $ "long" : argumentTypes
PointerType -> reverse $ "long" : argumentTypes
VoidType -> reverse argumentTypes
magicArgValues = case retcat of
VoidType -> reverse argumentNames
_ -> reverse $ "0" : argumentNames
words' = case retcat of
VoidType -> words
ByteType -> words ++ [ 0x101f ] -- move.b (a7)+,d0
WordType -> words ++ [ 0x301f ] -- move.w (a7)+,d0
LongType -> words ++ [ 0x201f ] -- move.l (a7)+,d0
PointerType -> words ++ [ 0x201f ] -- move.l (a7)+,d0
in PP.render $
PP.text rettype <+> PP.text "__attribute__((stdcall))" <+> helper
<> PP.parens (PP.hsep $ PP.punctuate PP.comma $ map PP.text magicArgTypes)
<+> PP.text("__asm__") <> PP.parens ( PP.doubleQuotes magic )
<> PP.semi
$+$
PP.text "static inline" <+> PP.text rettype <+> PP.text name
<+> PP.parens (PP.hsep $ PP.punctuate PP.comma $ zipWith (\t n -> PP.text t <+> PP.text n) argumentTypes argumentNames) $$
PP.text "{" $+$ (PP.nest 4 $
(if retcat == VoidType then PP.empty else PP.text "return") <+>
helper <> PP.parens (PP.hsep $ PP.punctuate PP.comma $ map PP.text magicArgValues) <> PP.semi
) $+$ PP.text "}\n\n"
outputItem typeMap (FunctionItem rettype name argumentTypes argumentNames words mbParamRegs) =
PP.render $ PP.render $
linkage <+> PP.text rettype <+> PP.text name linkage <+> PP.text rettype <+> PP.text name
<+> PP.parens (PP.hsep $ PP.punctuate PP.comma $ map PP.text arguments) $$ <+> PP.parens (PP.hsep $ PP.punctuate PP.comma $ zipWith (\t n -> PP.text t <+> PP.text n) argumentTypes argumentNames) $$
if isJust mbCategories && not (null words) if isJust mbCategories && not (null words)
then then
PP.text "{" $+$ (PP.nest 4 $ PP.text "{" $+$ (PP.nest 4 $
@ -119,8 +161,7 @@ outputItem typeMap (FunctionItem rettype name arguments words mbParamRegs) =
tooltrap = True -- trapnum >= 0xA800 tooltrap = True -- trapnum >= 0xA800
linkage | null words = PP.text "extern" linkage | null words = PP.text "extern"
| otherwise = PP.text "static inline" | otherwise = PP.text "static inline"
argumentNames = map (trim . reverse . takeWhile isAlphaNum . reverse . trim) arguments
argumentTypes = map (trim . reverse . dropWhile isAlphaNum . reverse . trim) arguments
mbCategories = do mbCategories = do
retcat <- classifyType typeMap rettype retcat <- classifyType typeMap rettype
@ -195,9 +236,9 @@ outputItem _ _ = ""
collectPragmas xs = evalState (mapM doit xs) Map.empty collectPragmas xs = evalState (mapM doit xs) Map.empty
where where
doit x@(PragmaParameterItem name params) = modify (Map.insert name params) >> return x doit x@(PragmaParameterItem name params) = modify (Map.insert name params) >> return x
doit (FunctionItem rettype name arguments inlines _) = do doit (FunctionItem rettype name argumentTypes argumentNames inlines _) = do
m <- get m <- get
return $ FunctionItem rettype name arguments inlines (Map.lookup name m) return $ FunctionItem rettype name argumentTypes argumentNames inlines (Map.lookup name m)
doit x = return x doit x = return x
parseTypeMap tm = Map.fromList $ map handleLine $ lines tm parseTypeMap tm = Map.fromList $ map handleLine $ lines tm
@ -236,6 +277,6 @@ processFile inputDir outputDir file
main = do main = do
[inputDir,outputDir] <- getArgs [inputDir,outputDir] <- getArgs
files <- getDirectoryContents inputDir files <- getDirectoryContents inputDir
System.IO.Error.try (createDirectory outputDir) Control.Exception.try (createDirectory outputDir) :: IO (Either Control.Exception.IOException ())
mapM (processFile inputDir outputDir) files mapM (processFile inputDir outputDir) files
return () return ()