Skip to content
Snippets Groups Projects
Commit e699643f authored by Ben Gamari's avatar Ben Gamari :turtle:
Browse files

CCall: Extend to test signed arguments and results

Closes #3.
parent 00a693b8
No related branches found
No related tags found
No related merge requests found
Pipeline #53680 failed
...@@ -4,7 +4,6 @@ module CCall ...@@ -4,7 +4,6 @@ module CCall
, testCCall , testCCall
) where ) where
import Numeric.Natural
import System.FilePath import System.FilePath
import System.IO.Temp import System.IO.Temp
import Test.QuickCheck import Test.QuickCheck
...@@ -17,7 +16,8 @@ import Number ...@@ -17,7 +16,8 @@ import Number
data CCallDesc data CCallDesc
= CCallDesc { callRet :: SomeNumber = CCallDesc { callRet :: SomeNumber
, callArgs :: [SomeNumber] , callRetSignedness :: Signedness
, callArgs :: [(Signedness, SomeNumber)]
} }
deriving (Show) deriving (Show)
...@@ -30,9 +30,10 @@ mAX_ARGS = 32 ...@@ -30,9 +30,10 @@ mAX_ARGS = 32
instance Arbitrary CCallDesc where instance Arbitrary CCallDesc where
arbitrary = do arbitrary = do
ret <- arbitrary ret <- arbitrary
ret_signedness <- arbitrary
n <- chooseInt (0, mAX_ARGS) n <- chooseInt (0, mAX_ARGS)
args <- vectorOf n arbitrary args <- vectorOf n arbitrary
return $ CCallDesc ret args return $ CCallDesc ret ret_signedness args
testCCall testCCall
:: Compiler :: Compiler
...@@ -44,11 +45,11 @@ testCCall comp c = ...@@ -44,11 +45,11 @@ testCCall comp c =
writeFile (tmpDir </> "test.cmm") (cCallCmm c) writeFile (tmpDir </> "test.cmm") (cCallCmm c)
compile comp tmpDir ["test_c.c", "test.cmm"] soName ["-shared", "-dynamic"] compile comp tmpDir ["test_c.c", "test.cmm"] soName ["-shared", "-dynamic"]
out <- runIt comp (tmpDir </> soName) out <- runIt comp (tmpDir </> soName)
let saw :: [Natural] let saw :: [Integer]
saw = map read (lines out) saw = map read (lines out)
expected :: [Natural] expected :: [Integer]
expected = map (\(SomeNumber e) -> toUnsigned e) (callArgs c) ++ [ret] expected = map (\(s, SomeNumber e) -> asInteger s e) (callArgs c) ++ [ret]
ret = case callRet c of SomeNumber n -> toUnsigned n ret = case callRet c of SomeNumber n -> asInteger (callRetSignedness c) n
return $ saw === expected return $ saw === expected
where where
...@@ -65,11 +66,14 @@ cStub c ...@@ -65,11 +66,14 @@ cStub c
] ]
where where
argBndrs = [ "arg"++show i | (i,_) <- zip [0::Int ..] (callArgs c) ] argBndrs = [ "arg"++show i | (i,_) <- zip [0::Int ..] (callArgs c) ]
argWidths = [ knownWidth @w | SomeNumber (_ :: Number w) <- callArgs c ] argTypes =
[ (signedness, knownWidth @w)
| (signedness, SomeNumber (_ :: Number w)) <- callArgs c
]
funcDef = unlines $ funcDef = unlines $
[ cType (retWidth c) <> " test_c(" <> argList <> ") {" ] ++ [ cType Unsigned (retWidth c) <> " test_c(" <> argList <> ") {" ] ++
zipWith printArg argWidths argBndrs ++ zipWith printArg argTypes argBndrs ++
[ " fflush(stdout);" [ " fflush(stdout);"
, " return " ++ show (someNumberToUnsigned $ callRet c) ++ "ULL;" , " return " ++ show (someNumberToUnsigned $ callRet c) ++ "ULL;"
, "}" , "}"
...@@ -77,39 +81,47 @@ cStub c ...@@ -77,39 +81,47 @@ cStub c
argList = argList =
commaList commaList
[ unwords [cType w, bndr] [ unwords [ty, bndr]
| (w, bndr) <- zip argWidths argBndrs | (ty, bndr) <- zip (map (uncurry cType) argTypes) argBndrs
] ]
printArg w bndr = printArg ty bndr =
" printf(" ++ quoted (formatStr w ++ "\\n") ++ ", " ++ bndr ++ ");" " printf(" ++ quoted (formatStr ty ++ "\\n") ++ ", " ++ bndr ++ ");"
quoted :: String -> String quoted :: String -> String
quoted s = "\"" ++ s ++ "\"" quoted s = "\"" ++ s ++ "\""
formatStr :: Width -> String formatStr :: (Signedness, Width) -> String
formatStr w = formatStr (_signedness, w) =
"0x%" ++ quoted ("PRIx"++show n) "0x%" ++ quoted ("PRIx"++show n)
where where
n = widthBits w n = widthBits w
cType :: Width -> String cType :: Signedness -> Width -> String
cType W8 = "uint8_t" cType signedness width = prefix ++ "int" ++ show n ++ "_t"
cType W16 = "uint16_t" where
cType W32 = "uint32_t" n = widthBits width
cType W64 = "uint64_t" prefix = case signedness of
Signed -> ""
Unsigned -> "u"
cCallCmm :: CCallDesc -> String cCallCmm :: CCallDesc -> String
cCallCmm c = unlines cCallCmm c = unlines
[ "test("++cmmWordType ++" buffer) {" [ "test("++cmmWordType ++" buffer) {"
, " "++cmmType (retWidth c)++" ret;" , " "++cmmType (retWidth c)++" ret;"
, " (ret) = foreign \"C\" test_c(" ++ argList ++ ");" , " (" ++ retHint ++ "ret) = foreign \"C\" test_c(" ++ argList ++ ");"
, " return ("++widenOp++"(ret));" , " return ("++widenOp++"(ret));"
, "}" , "}"
] ]
where where
retHint = case callRetSignedness c of
Signed -> "\"signed\" "
Unsigned -> ""
widenOp = "%zx" ++ show (widthBits wordSize) widenOp = "%zx" ++ show (widthBits wordSize)
argList = argList =
commaList commaList
[ exprToCmm $ ELit e [ exprToCmm (ELit e) ++ hint
| SomeNumber e <- callArgs c | (signedness, SomeNumber e) <- callArgs c
, let hint = case signedness of
Signed -> " \"signed\""
Unsigned -> ""
] ]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment