@@ -24,15 +24,19 @@ import Control.Monad
24import Debug.Trace
24import Debug.Trace
26codegenC :: CodeGenerator
26codegenC :: CodeGenerator
27−codegenC ci = codegenC' (simpleDecls ci)
27+codegenC ci = do codegenC' (simpleDecls ci)
28− (outputFile ci)
28+ (outputFile ci)
29− (outputType ci)
29+ (outputType ci)
30− (includes ci)
30+ (includes ci)
31− (compileObjs ci)
31+ (compileObjs ci)
32− (map mkLib (compileLibs ci) ++
32+ (map mkLib (compileLibs ci) ++
33− map incdir (importDirs ci))
33+ map incdir (importDirs ci))
34− (compilerFlags ci)
34+ (compilerFlags ci)
35− (debugLevel ci)
37+ (debugLevel ci)
38+ when (interfaces ci) $
39+ codegenH (exportDecls ci)
37 where mkLib l = "-l" ++ l
41 where mkLib l = "-l" ++ l
38 incdir i = "-I" ++ i
42 incdir i = "-I" ++ i
@@ -44,17 +48,20 @@ codegenC' :: [(Name, SDecl)] ->
44 [String] -> -- extra object files
48 [String] -> -- extra object files
45 [String] -> -- extra compiler flags (libraries)
49 [String] -> -- extra compiler flags (libraries)
46 [String] -> -- extra compiler flags (anything)
50 [String] -> -- extra compiler flags (anything)
52+ Bool -> -- interfaces too (so make a .o instead)
47 DbgLevel ->
53 DbgLevel ->
49−codegenC' defs out exec incs objs libs flags dbg
55+codegenC' defs out exec incs objs libs flags exports iface dbg
50 = do -- print defs
56 = do -- print defs
51 let bc = map toBC defs
57 let bc = map toBC defs
52 let h = concatMap toDecl (map fst bc)
58 let h = concatMap toDecl (map fst bc)
53 let cc = concatMap (uncurry toC) bc
59 let cc = concatMap (uncurry toC) bc
60+ let hi = concatMap ifaceC (concatMap getExp exports)
54 d <- getDataDir
61 d <- getDataDir
55 mprog <- readFile (d </> "rts" </> "idris_main" <.> "c")
62 mprog <- readFile (d </> "rts" </> "idris_main" <.> "c")
56 let cout = headers incs ++ debug dbg ++ h ++ cc ++
63 let cout = headers incs ++ debug dbg ++ h ++ cc ++
57− (if (exec == Executable) then mprog else "")
64+ (if (exec == Executable) then mprog else hi)
58 case exec of
65 case exec of
59 MavenProject -> putStrLn ("FAILURE: output type not supported")
66 MavenProject -> putStrLn ("FAILURE: output type not supported")
60 Raw -> writeFile out cout
67 Raw -> writeFile out cout
@@ -67,21 +74,23 @@ codegenC' defs out exec incs objs libs flags dbg
67 libFlags <- getLibFlags
74 libFlags <- getLibFlags
68 incFlags <- getIncFlags
75 incFlags <- getIncFlags
69 let args = [gccDbg dbg] ++
76 let args = [gccDbg dbg] ++
70− gccFlags ++
77+ gccFlags iface ++
71 -- # Any flags defined here which alter the RTS API must also be added to config.mk
78 -- # Any flags defined here which alter the RTS API must also be added to config.mk
72 ["-DHAS_PTHREAD", "-DIDRIS_ENABLE_STATS", "-msse2",
79 ["-DHAS_PTHREAD", "-DIDRIS_ENABLE_STATS", "-msse2",
73 "-I."] ++ objs ++ ["-x", "c"] ++
80 "-I."] ++ objs ++ ["-x", "c"] ++
74 (if (exec == Executable) then [] else ["-c"]) ++
81 (if (exec == Executable) then [] else ["-c"]) ++
76− concatMap words libFlags ++
83+ (if not iface then concatMap words libFlags else []) ++
77 concatMap words incFlags ++
84 concatMap words incFlags ++
78− concatMap words libs ++
85+ (if not iface then concatMap words libs else []) ++
79 concatMap words flags ++
86 concatMap words flags ++
80 ["-o", out]
87 ["-o", out]
81−-- putStrLn gcc
88+-- putStrLn (show args)
82 exit <- rawSystem comp args
89 exit <- rawSystem comp args
83 when (exit /= ExitSuccess) $
90 when (exit /= ExitSuccess) $
84 putStrLn ("FAILURE: " ++ show comp ++ " " ++ show args)
91 putStrLn ("FAILURE: " ++ show comp ++ " " ++ show args)
93+ getExp (Export _ _ exp) = exp
86headers xs =
95headers xs =
@@ -93,7 +102,8 @@ debug _ = ""
94-- We're using signed integers now. Make sure we get consistent semantics
103-- We're using signed integers now. Make sure we get consistent semantics
95-- out of them from gcc. See e.g. http://thiemonagel.de/2010/01/signed-integer-overflow/
104-- out of them from gcc. See e.g. http://thiemonagel.de/2010/01/signed-integer-overflow/
105+gccFlags i = if i then ["-fwrapv"]
96−gccFlags = ["-fwrapv", "-fno-strict-overflow"]
106+ else ["-fwrapv", "-fno-strict-overflow"]
98gccDbg DEBUG = "-g"
108gccDbg DEBUG = "-g"
99gccDbg TRACE = "-O2"
109gccDbg TRACE = "-O2"
@@ -311,7 +321,7 @@ toFType (FApp c [_,ity])
311 | c == sUN "C_IntT" = FArith (toAType ity)
321 | c == sUN "C_IntT" = FArith (toAType ity)
312toFType (FApp c [_])
322toFType (FApp c [_])
313 | c == sUN "C_Any" = FAny
323 | c == sUN "C_Any" = FAny
314−toFType t = error (show t ++ " not defined in toFType")
324+toFType t = FAny
316c_irts (FArith (ATInt ITNative)) l x = l ++ "MKINT((i_int)(" ++ x ++ "))"
326c_irts (FArith (ATInt ITNative)) l x = l ++ "MKINT((i_int)(" ++ x ++ "))"
317c_irts (FArith (ATInt ITChar)) l x = c_irts (FArith (ATInt ITNative)) l x
327c_irts (FArith (ATInt ITChar)) l x = c_irts (FArith (ATInt ITNative)) l x
@@ -561,3 +571,91 @@ doOp _ op args = error "doOp of (" ++ show op ++ ") not implemented, arguments (
562flUnOp :: String -> String -> String
572flUnOp :: String -> String -> String
563flUnOp name val = "MKFLOAT(vm, " ++ name ++ "(GETFLOAT(" ++ val ++ ")))"
573flUnOp name val = "MKFLOAT(vm, " ++ name ++ "(GETFLOAT(" ++ val ++ ")))"
575+-------------------- Interface file generation
577+-- First, the wrappers in the C file
579+ifaceC :: Export -> String
580+ifaceC (ExportData n) = "typedef VAL " ++ cdesc n ++ ";\n"
581+ifaceC (ExportFun n cn ret args)
582+ = ctype ret ++ " " ++ cdesc cn ++
583+ "(VM* vm" ++ showArgs (zip argNames args) ++ ") {\n"
584+ ++ mkBody n (zip argNames args) ret ++ "}\n\n"
585+ where showArgs [] = ""
586+ showArgs ((n, t) : ts) = ", " ++ ctype t ++ " " ++ n ++
589+ argNames = zipWith (++) (repeat "arg") (map show [0..])
591+mkBody n as t = indent 1 ++ "INITFRAME;\n" ++
592+ indent 1 ++ "RESERVE(" ++ show (length as) ++ ");\n" ++
593+ push 0 as ++ call n ++ retval t
594+ where push i [] = ""
595+ push i ((n, t) : ts) = indent 1 ++ c_irts (toFType t)
596+ ("TOP(" ++ show i ++ ") = ") n
597+ ++ ";\n" ++ push (i + 1) ts
599+ call _ = indent 1 ++ "STOREOLD;\n" ++
600+ indent 1 ++ "BASETOP(0);\n" ++
601+ indent 1 ++ "ADDTOP(" ++ show (length as) ++ ");\n" ++
602+ indent 1 ++ "CALL(" ++ cname n ++ ");\n"
604+ retval t = indent 1 ++ "return " ++ irts_c (toFType t) "RVAL" ++ ";\n"
607+ | c == sUN "C_Str" = "char*"
608+ | c == sUN "C_Float" = "float"
609+ | c == sUN "C_Ptr" = "void*"
610+ | c == sUN "C_MPtr" = "void*"
611+ | c == sUN "C_Unit" = "void"
612+ctype (FApp c [_,ity])
613+ | c == sUN "C_IntT" = carith ity
615+ | c == sUN "C_Any" = "VAL"
617+ctype FUnknown = "void*"
618+ctype FWorld = "void*"
619+ctype t = error "Can't happen: Not a valid interface type " ++ show t
622+ | i == sUN "C_IntChar" = "char"
623+ | i == sUN "C_IntNative" = "int"
624+carith t = error "Can't happen: Not an exportable arithmetic type"
627+cdesc s = error "Can't happen: Not a valid C name"
629+-- Then, the header files
631+codegenH :: [ExportIFace] -> IO ()
632+codegenH es = mapM_ writeIFace es
634+writeIFace :: ExportIFace -> IO ()
635+writeIFace (Export ffic hdr exps)
636+ | ffic == sUN "FFI_C"
637+ = do let hfile = "#ifndef " ++ hdr_guard hdr ++ "\n" ++
638+ "#define " ++ hdr_guard hdr ++ "\n\n" ++
639+ "#include <idris_rts.h>\n\n" ++
640+ concatMap hdr_export exps ++ "\n" ++
643+ | otherwise = return ()
645+hdr_guard x = "__" ++ map hchar x
646+ where hchar x | isAlphaNum x = toUpper x
649+hdr_export :: Export -> String
650+hdr_export (ExportData n) = "typedef VAL " ++ cdesc n ++ ";\n"
651+hdr_export (ExportFun n cn ret args)
652+ = ctype ret ++ " " ++ cdesc cn ++
653+ "(VM* vm" ++ showArgs (zip argNames args) ++ ");\n"
654+ where showArgs [] = ""
655+ showArgs ((n, t) : ts) = ", " ++ ctype t ++ " " ++ n ++
658+ argNames = zipWith (++) (repeat "arg") (map show [0..])