on 175a735 help sign in
Idris-dev/src/IRTS/CodegenC.hs
500 lines 25 kB history raw
1module IRTS.CodegenC (codegenC) where
3import Idris.AbsSyntax
4import IRTS.Bytecode
5import IRTS.Lang
6import IRTS.Simplified
7import IRTS.System
8import IRTS.CodegenCommon
9import Idris.Core.TT
10import Paths_idris
11import Util.System
13import Numeric
14import Data.Char
15import Data.List (intercalate)
16import System.Process
17import System.Exit
18import System.IO
19import System.Directory
20import System.FilePath ((</>), (<.>))
21import Control.Monad
23codegenC :: CodeGenerator
24codegenC ci = codegenC' (simpleDecls ci)
25 (outputFile ci)
26 (outputType ci)
27 (includes ci)
28 (concatMap mkObj (compileObjs ci))
29 (concatMap mkLib (compileLibs ci) ++
30 concatMap incdir (importDirs ci))
31 (concatMap mkFlag (compilerFlags ci))
32 (debugLevel ci)
34 where mkObj f = f ++ " "
35 mkLib l = "-l" ++ l ++ " "
36 mkFlag l = l ++ " "
37 incdir i = "-I" ++ i ++ " "
39codegenC' :: [(Name, SDecl)] ->
40 String -> -- output file name
41 OutputType -> -- generate executable if True, only .o if False
42 [FilePath] -> -- include files
43 String -> -- extra object files
44 String -> -- extra compiler flags (libraries)
45 String -> -- extra compiler flags (anything)
46 DbgLevel ->
47 IO ()
48codegenC' defs out exec incs objs libs flags dbg
49 = do -- print defs
50 let bc = map toBC defs
51 let h = concatMap toDecl (map fst bc)
52 let cc = concatMap (uncurry toC) bc
53 d <- getDataDir
54 mprog <- readFile (d </> "rts" </> "idris_main" <.> "c")
55 let cout = headers incs ++ debug dbg ++ h ++ cc ++
56 (if (exec == Executable) then mprog else "")
57 case exec of
58 MavenProject -> putStrLn ("FAILURE: output type not supported")
59 Raw -> writeFile out cout
60 _ -> do
61 (tmpn, tmph) <- tempfile
62 hPutStr tmph cout
63 hFlush tmph
64 hClose tmph
65 comp <- getCC
66 libFlags <- getLibFlags
67 incFlags <- getIncFlags
68 let gcc = comp ++ " " ++
69 gccDbg dbg ++ " " ++
70 gccFlags ++
71 " -I. " ++ objs ++ " -x c " ++
72 (if (exec == Executable) then "" else " -c ") ++
73 " " ++ tmpn ++
74 " " ++ libFlags ++
75 " " ++ incFlags ++
76 " " ++ libs ++
77 " " ++ flags ++
78 " -o " ++ out
79-- putStrLn gcc
80 exit <- system gcc
81 when (exit /= ExitSuccess) $
82 putStrLn ("FAILURE: " ++ gcc)
84headers xs =
85 concatMap
86 (\h -> "#include <" ++ h ++ ">\n")
87 (xs ++ ["idris_rts.h", "idris_bitstring.h", "idris_stdfgn.h", "assert.h"])
89debug TRACE = "#define IDRIS_TRACE\n\n"
90debug _ = ""
92-- We're using signed integers now. Make sure we get consistent semantics
93-- out of them from gcc. See e.g. http://thiemonagel.de/2010/01/signed-integer-overflow/
94gccFlags = " -fwrapv -fno-strict-overflow"
96gccDbg DEBUG = "-g"
97gccDbg TRACE = "-O2"
98gccDbg _ = "-O2"
100cname :: Name -> String
101cname n = "_idris_" ++ concatMap cchar (showCG n)
102 where cchar x | isAlpha x || isDigit x = [x]
103 | otherwise = "_" ++ show (fromEnum x) ++ "_"
105indent :: Int -> String
106indent n = replicate (n*4) ' '
108creg RVal = "RVAL"
109creg (L i) = "LOC(" ++ show i ++ ")"
110creg (T i) = "TOP(" ++ show i ++ ")"
111creg Tmp = "REG1"
113toDecl :: Name -> String
114toDecl f = "void " ++ cname f ++ "(VM*, VAL*);\n"
116toC :: Name -> [BC] -> String
117toC f code
118 = -- "/* " ++ show code ++ "*/\n\n" ++
119 "void " ++ cname f ++ "(VM* vm, VAL* oldbase) {\n" ++
120 indent 1 ++ "INITFRAME;\n" ++
121 concatMap (bcc 1) code ++ "}\n\n"
123showCStr :: String -> String
124showCStr s = '"' : foldr ((++) . showChar) "\"" s
125 where
126 showChar :: Char -> String
127 showChar '"' = "\\\""
128 showChar '\\' = "\\\\"
129 showChar c
130 -- Note: we need the double quotes around the codes because otherwise
131 -- "\n3" would get encoded as "\x0a3", which is incorrect.
132 -- Instead, we opt for "\x0a""3" and let the C compiler deal with it.
133 | ord c < 0x10 = "\"\"\\x0" ++ showHex (ord c) "\"\""
134 | ord c < 0x20 = "\"\"\\x" ++ showHex (ord c) "\"\""
135 | ord c < 0x7f = [c] -- 0x7f = \DEL
136 | ord c < 0x100 = "\"\"\\x" ++ showHex (ord c) "\"\""
137 | otherwise = error $ "non-8-bit character in string literal: " ++ show c
139bcc :: Int -> BC -> String
140bcc i (ASSIGN l r) = indent i ++ creg l ++ " = " ++ creg r ++ ";\n"
141bcc i (ASSIGNCONST l c)
142 = indent i ++ creg l ++ " = " ++ mkConst c ++ ";\n"
143 where
144 mkConst (I i) = "MKINT(" ++ show i ++ ")"
145 mkConst (BI i) | i < (2^30) = "MKINT(" ++ show i ++ ")"
146 | otherwise = "MKBIGC(vm,\"" ++ show i ++ "\")"
147 mkConst (Fl f) = "MKFLOAT(vm, " ++ show f ++ ")"
148 mkConst (Ch c) = "MKINT(" ++ show (fromEnum c) ++ ")"
149 mkConst (Str s) = "MKSTR(vm, " ++ showCStr s ++ ")"
150 mkConst (B8 x) = "idris_b8const(vm, " ++ show x ++ "U)"
151 mkConst (B16 x) = "idris_b16const(vm, " ++ show x ++ "U)"
152 mkConst (B32 x) = "idris_b32const(vm, " ++ show x ++ "UL)"
153 mkConst (B64 x) = "idris_b64const(vm, " ++ show x ++ "ULL)"
154 mkConst _ = "MKINT(42424242)"
155bcc i (UPDATE l r) = indent i ++ creg l ++ " = " ++ creg r ++ ";\n"
156bcc i (MKCON l tag args)
157 = indent i ++ "allocCon(" ++ creg Tmp ++ ", vm, " ++ show tag ++ "," ++
158 show (length args) ++ ", 0);\n" ++
159 indent i ++ setArgs 0 args ++ "\n" ++
160 indent i ++ creg l ++ " = " ++ creg Tmp ++ ";\n"
162-- "MKCON(vm, " ++ creg l ++ ", " ++ show tag ++ ", " ++
163-- show (length args) ++ concatMap showArg args ++ ");\n"
164 where showArg r = ", " ++ creg r
165 setArgs i [] = ""
166 setArgs i (x : xs) = "SETARG(" ++ creg Tmp ++ ", " ++ show i ++ ", " ++ creg x ++
167 "); " ++ setArgs (i + 1) xs
169bcc i (PROJECT l loc a) = indent i ++ "PROJECT(vm, " ++ creg l ++ ", " ++ show loc ++
170 ", " ++ show a ++ ");\n"
171bcc i (PROJECTINTO r t idx)
172 = indent i ++ creg r ++ " = GETARG(" ++ creg t ++ ", " ++ show idx ++ ");\n"
173bcc i (CASE True r code def)
174 | length code < 4 = showCase i def code
175 where
176 showCode :: Int -> [BC] -> String
177 showCode i bc = "{\n" ++ concatMap (bcc (i + 1)) bc ++
178 indent i ++ "}\n"
180 showCase :: Int -> Maybe [BC] -> [(Int, [BC])] -> String
181 showCase i Nothing [(t, c)] = showCode i c
182 showCase i (Just def) [] = showCode i def
183 showCase i def ((t, c) : cs)
184 = indent i ++ "if (CTAG(" ++ creg r ++ ") == " ++ show t ++ ") " ++ showCode i c
185 ++ indent i ++ "else " ++ showCase i def cs
187bcc i (CASE safe r code def)
188 = indent i ++ "switch(" ++ ctag safe ++ "(" ++ creg r ++ ")) {\n" ++
189 concatMap (showCase i) code ++
190 showDef i def ++
191 indent i ++ "}\n"
192 where
193 ctag True = "CTAG"
194 ctag False = "TAG"
196 showCase i (t, bc) = indent i ++ "case " ++ show t ++ ":\n"
197 ++ concatMap (bcc (i+1)) bc ++ indent (i + 1) ++ "break;\n"
198 showDef i Nothing = ""
199 showDef i (Just c) = indent i ++ "default:\n"
200 ++ concatMap (bcc (i+1)) c ++ indent (i + 1) ++ "break;\n"
201bcc i (CONSTCASE r code def)
202 | intConsts code
203-- = indent i ++ "switch(GETINT(" ++ creg r ++ ")) {\n" ++
204-- concatMap (showCase i) code ++
205-- showDef i def ++
206-- indent i ++ "}\n"
207 = concatMap (iCase (creg r)) code ++
208 indent i ++ "{\n" ++ showDefS i def ++ indent i ++ "}\n"
209 | strConsts code
210 = concatMap (strCase ("GETSTR(" ++ creg r ++ ")")) code ++
211 indent i ++ "{\n" ++ showDefS i def ++ indent i ++ "}\n"
212 | bigintConsts code
213 = concatMap (biCase (creg r)) code ++
214 indent i ++ "{\n" ++ showDefS i def ++ indent i ++ "}\n"
215 | otherwise = error $ "Can't happen: Can't compile const case " ++ show code
216 where
217 intConsts ((I _, _ ) : _) = True
218 intConsts ((Ch _, _ ) : _) = True
219 intConsts _ = False
221 bigintConsts ((BI _, _ ) : _) = True
222 bigintConsts _ = False
224 strConsts ((Str _, _ ) : _) = True
225 strConsts _ = False
227 strCase sv (s, bc) =
228 indent i ++ "if (strcmp(" ++ sv ++ ", " ++ show s ++ ") == 0) {\n" ++
229 concatMap (bcc (i+1)) bc ++ indent i ++ "} else\n"
230 biCase bv (BI b, bc) =
231 indent i ++ "if (bigEqConst(" ++ bv ++ ", " ++ show b ++ ")) {\n"
232 ++ concatMap (bcc (i+1)) bc ++ indent i ++ "} else\n"
233 iCase v (I b, bc) =
234 indent i ++ "if (GETINT(" ++ v ++ ") == " ++ show b ++ ") {\n"
235 ++ concatMap (bcc (i+1)) bc ++ indent i ++ "} else\n"
236 iCase v (Ch b, bc) =
237 indent i ++ "if (GETINT(" ++ v ++ ") == " ++ show (fromEnum b) ++ ") {\n"
238 ++ concatMap (bcc (i+1)) bc ++ indent i ++ "} else\n"
240 showCase i (t, bc) = indent i ++ "case " ++ show t ++ ":\n"
241 ++ concatMap (bcc (i+1)) bc ++
242 indent (i + 1) ++ "break;\n"
243 showDef i Nothing = ""
244 showDef i (Just c) = indent i ++ "default:\n"
245 ++ concatMap (bcc (i+1)) c ++
246 indent (i + 1) ++ "break;\n"
247 showDefS i Nothing = ""
248 showDefS i (Just c) = concatMap (bcc (i+1)) c
250bcc i (CALL n) = indent i ++ "CALL(" ++ cname n ++ ");\n"
251bcc i (TAILCALL n) = indent i ++ "TAILCALL(" ++ cname n ++ ");\n"
252bcc i (SLIDE n) = indent i ++ "SLIDE(vm, " ++ show n ++ ");\n"
253bcc i REBASE = indent i ++ "REBASE;\n"
254bcc i (RESERVE 0) = ""
255bcc i (RESERVE n) = indent i ++ "RESERVE(" ++ show n ++ ");\n"
256bcc i (ADDTOP 0) = ""
257bcc i (ADDTOP n) = indent i ++ "ADDTOP(" ++ show n ++ ");\n"
258bcc i (TOPBASE n) = indent i ++ "TOPBASE(" ++ show n ++ ");\n"
259bcc i (BASETOP n) = indent i ++ "BASETOP(" ++ show n ++ ");\n"
260bcc i STOREOLD = indent i ++ "STOREOLD;\n"
261bcc i (OP l fn args) = indent i ++ doOp (creg l ++ " = ") fn args ++ ";\n"
262bcc i (FOREIGNCALL l LANG_C rty fn args)
263 = indent i ++
264 c_irts rty (creg l ++ " = ")
265 (fn ++ "(" ++ showSep "," (map fcall args) ++ ")") ++ ";\n"
266 where fcall (t, arg) = irts_c t (creg arg)
267bcc i (NULL r) = indent i ++ creg r ++ " = NULL;\n" -- clear, so it'll be GCed
268bcc i (ERROR str) = indent i ++ "fprintf(stderr, " ++ show str ++ "); assert(0); exit(-1);"
269-- bcc i _ = indent i ++ "// not done yet\n"
273c_irts (FArith (ATInt ITNative)) l x = l ++ "MKINT((i_int)(" ++ x ++ "))"
274c_irts (FArith (ATInt ITChar)) l x = c_irts (FArith (ATInt ITNative)) l x
275c_irts (FArith (ATInt (ITFixed ity))) l x
276 = l ++ "idris_b" ++ show (nativeTyWidth ity) ++ "const(vm, " ++ x ++ ")"
277c_irts FString l x = l ++ "MKSTR(vm, " ++ x ++ ")"
278c_irts FUnit l x = x
279c_irts FPtr l x = l ++ "MKPTR(vm, " ++ x ++ ")"
280c_irts FManagedPtr l x = l ++ "MKMPTR(vm, " ++ x ++ ")"
281c_irts (FArith ATFloat) l x = l ++ "MKFLOAT(vm, " ++ x ++ ")"
282c_irts FAny l x = l ++ x
284irts_c (FArith (ATInt ITNative)) x = "GETINT(" ++ x ++ ")"
285irts_c (FArith (ATInt ITChar)) x = irts_c (FArith (ATInt ITNative)) x
286irts_c (FArith (ATInt (ITFixed ity))) x
287 = "(" ++ x ++ "->info.bits" ++ show (nativeTyWidth ity) ++ ")"
288irts_c FString x = "GETSTR(" ++ x ++ ")"
289irts_c FUnit x = x
290irts_c FPtr x = "GETPTR(" ++ x ++ ")"
291irts_c FManagedPtr x = "GETMPTR(" ++ x ++ ")"
292irts_c (FArith ATFloat) x = "GETFLOAT(" ++ x ++ ")"
293irts_c FAny x = x
295bitOp v op ty args = v ++ "idris_b" ++ show (nativeTyWidth ty) ++ op ++ "(vm, " ++ intercalate ", " (map creg args) ++ ")"
297bitCoerce v op input output arg
298 = v ++ "idris_b" ++ show (nativeTyWidth input) ++ op ++ show (nativeTyWidth output) ++ "(vm, " ++ creg arg ++ ")"
300signedTy :: NativeTy -> String
301signedTy t = "int" ++ show (nativeTyWidth t) ++ "_t"
303doOp v (LPlus (ATInt ITNative)) [l, r] = v ++ "ADD(" ++ creg l ++ ", " ++ creg r ++ ")"
304doOp v (LMinus (ATInt ITNative)) [l, r] = v ++ "INTOP(-," ++ creg l ++ ", " ++ creg r ++ ")"
305doOp v (LTimes (ATInt ITNative)) [l, r] = v ++ "MULT(" ++ creg l ++ ", " ++ creg r ++ ")"
306doOp v (LUDiv ITNative) [l, r] = v ++ "UINTOP(/," ++ creg l ++ ", " ++ creg r ++ ")"
307doOp v (LSDiv (ATInt ITNative)) [l, r] = v ++ "INTOP(/," ++ creg l ++ ", " ++ creg r ++ ")"
308doOp v (LURem ITNative) [l, r] = v ++ "UINTOP(%," ++ creg l ++ ", " ++ creg r ++ ")"
309doOp v (LSRem (ATInt ITNative)) [l, r] = v ++ "INTOP(%," ++ creg l ++ ", " ++ creg r ++ ")"
310doOp v (LAnd ITNative) [l, r] = v ++ "INTOP(&," ++ creg l ++ ", " ++ creg r ++ ")"
311doOp v (LOr ITNative) [l, r] = v ++ "INTOP(|," ++ creg l ++ ", " ++ creg r ++ ")"
312doOp v (LXOr ITNative) [l, r] = v ++ "INTOP(^," ++ creg l ++ ", " ++ creg r ++ ")"
313doOp v (LSHL ITNative) [l, r] = v ++ "INTOP(<<," ++ creg l ++ ", " ++ creg r ++ ")"
314doOp v (LLSHR ITNative) [l, r] = v ++ "UINTOP(>>," ++ creg l ++ ", " ++ creg r ++ ")"
315doOp v (LASHR ITNative) [l, r] = v ++ "INTOP(>>," ++ creg l ++ ", " ++ creg r ++ ")"
316doOp v (LCompl ITNative) [x] = v ++ "INTOP(~," ++ creg x ++ ")"
317doOp v (LEq (ATInt ITNative)) [l, r] = v ++ "INTOP(==," ++ creg l ++ ", " ++ creg r ++ ")"
318doOp v (LSLt (ATInt ITNative)) [l, r] = v ++ "INTOP(<," ++ creg l ++ ", " ++ creg r ++ ")"
319doOp v (LSLe (ATInt ITNative)) [l, r] = v ++ "INTOP(<=," ++ creg l ++ ", " ++ creg r ++ ")"
320doOp v (LSGt (ATInt ITNative)) [l, r] = v ++ "INTOP(>," ++ creg l ++ ", " ++ creg r ++ ")"
321doOp v (LSGe (ATInt ITNative)) [l, r] = v ++ "INTOP(>=," ++ creg l ++ ", " ++ creg r ++ ")"
322doOp v (LLt ITNative) [l, r] = v ++ "UINTOP(<," ++ creg l ++ ", " ++ creg r ++ ")"
323doOp v (LLe ITNative) [l, r] = v ++ "UINTOP(<=," ++ creg l ++ ", " ++ creg r ++ ")"
324doOp v (LGt ITNative) [l, r] = v ++ "UINTOP(>," ++ creg l ++ ", " ++ creg r ++ ")"
325doOp v (LGe ITNative) [l, r] = v ++ "UINTOP(>=," ++ creg l ++ ", " ++ creg r ++ ")"
327doOp v (LPlus (ATInt ITChar)) [l, r] = doOp v (LPlus (ATInt ITNative)) [l, r]
328doOp v (LMinus (ATInt ITChar)) [l, r] = doOp v (LMinus (ATInt ITNative)) [l, r]
329doOp v (LTimes (ATInt ITChar)) [l, r] = doOp v (LTimes (ATInt ITNative)) [l, r]
330doOp v (LUDiv ITChar) [l, r] = doOp v (LUDiv ITNative) [l, r]
331doOp v (LSDiv (ATInt ITChar)) [l, r] = doOp v (LSDiv (ATInt ITNative)) [l, r]
332doOp v (LURem ITChar) [l, r] = doOp v (LURem ITNative) [l, r]
333doOp v (LSRem (ATInt ITChar)) [l, r] = doOp v (LSRem (ATInt ITNative)) [l, r]
334doOp v (LAnd ITChar) [l, r] = doOp v (LAnd ITNative) [l, r]
335doOp v (LOr ITChar) [l, r] = doOp v (LOr ITNative) [l, r]
336doOp v (LXOr ITChar) [l, r] = doOp v (LXOr ITNative) [l, r]
337doOp v (LSHL ITChar) [l, r] = doOp v (LSHL ITNative) [l, r]
338doOp v (LLSHR ITChar) [l, r] = doOp v (LLSHR ITNative) [l, r]
339doOp v (LASHR ITChar) [l, r] = doOp v (LASHR ITNative) [l, r]
340doOp v (LCompl ITChar) [x] = doOp v (LCompl ITNative) [x]
341doOp v (LEq (ATInt ITChar)) [l, r] = doOp v (LEq (ATInt ITNative)) [l, r]
342doOp v (LSLt (ATInt ITChar)) [l, r] = doOp v (LSLt (ATInt ITNative)) [l, r]
343doOp v (LSLe (ATInt ITChar)) [l, r] = doOp v (LSLe (ATInt ITNative)) [l, r]
344doOp v (LSGt (ATInt ITChar)) [l, r] = doOp v (LSGt (ATInt ITNative)) [l, r]
345doOp v (LSGe (ATInt ITChar)) [l, r] = doOp v (LSGe (ATInt ITNative)) [l, r]
346doOp v (LLt ITChar) [l, r] = doOp v (LLt ITNative) [l, r]
347doOp v (LLe ITChar) [l, r] = doOp v (LLe ITNative) [l, r]
348doOp v (LGt ITChar) [l, r] = doOp v (LGt ITNative) [l, r]
349doOp v (LGe ITChar) [l, r] = doOp v (LGe ITNative) [l, r]
351doOp v (LPlus ATFloat) [l, r] = v ++ "FLOATOP(+," ++ creg l ++ ", " ++ creg r ++ ")"
352doOp v (LMinus ATFloat) [l, r] = v ++ "FLOATOP(-," ++ creg l ++ ", " ++ creg r ++ ")"
353doOp v (LTimes ATFloat) [l, r] = v ++ "FLOATOP(*," ++ creg l ++ ", " ++ creg r ++ ")"
354doOp v (LSDiv ATFloat) [l, r] = v ++ "FLOATOP(/," ++ creg l ++ ", " ++ creg r ++ ")"
355doOp v (LEq ATFloat) [l, r] = v ++ "FLOATBOP(==," ++ creg l ++ ", " ++ creg r ++ ")"
356doOp v (LSLt ATFloat) [l, r] = v ++ "FLOATBOP(<," ++ creg l ++ ", " ++ creg r ++ ")"
357doOp v (LSLe ATFloat) [l, r] = v ++ "FLOATBOP(<=," ++ creg l ++ ", " ++ creg r ++ ")"
358doOp v (LSGt ATFloat) [l, r] = v ++ "FLOATBOP(>," ++ creg l ++ ", " ++ creg r ++ ")"
359doOp v (LSGe ATFloat) [l, r] = v ++ "FLOATBOP(>=," ++ creg l ++ ", " ++ creg r ++ ")"
361doOp v (LIntFloat ITBig) [x] = v ++ "idris_castBigFloat(vm, " ++ creg x ++ ")"
362doOp v (LFloatInt ITBig) [x] = v ++ "idris_castFloatBig(vm, " ++ creg x ++ ")"
363doOp v (LPlus (ATInt ITBig)) [l, r] = v ++ "idris_bigPlus(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
364doOp v (LMinus (ATInt ITBig)) [l, r] = v ++ "idris_bigMinus(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
365doOp v (LTimes (ATInt ITBig)) [l, r] = v ++ "idris_bigTimes(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
366doOp v (LSDiv (ATInt ITBig)) [l, r] = v ++ "idris_bigDivide(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
367doOp v (LSRem (ATInt ITBig)) [l, r] = v ++ "idris_bigMod(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
368doOp v (LEq (ATInt ITBig)) [l, r] = v ++ "idris_bigEq(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
369doOp v (LSLt (ATInt ITBig)) [l, r] = v ++ "idris_bigLt(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
370doOp v (LSLe (ATInt ITBig)) [l, r] = v ++ "idris_bigLe(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
371doOp v (LSGt (ATInt ITBig)) [l, r] = v ++ "idris_bigGt(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
372doOp v (LSGe (ATInt ITBig)) [l, r] = v ++ "idris_bigGe(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
374doOp v LStrConcat [l,r] = v ++ "idris_concat(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
375doOp v LStrLt [l,r] = v ++ "idris_strlt(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
376doOp v LStrEq [l,r] = v ++ "idris_streq(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
377doOp v LStrLen [x] = v ++ "idris_strlen(vm, " ++ creg x ++ ")"
379doOp v (LIntFloat ITNative) [x] = v ++ "idris_castIntFloat(" ++ creg x ++ ")"
380doOp v (LFloatInt ITNative) [x] = v ++ "idris_castFloatInt(" ++ creg x ++ ")"
381doOp v (LSExt ITNative ITBig) [x] = v ++ "idris_castIntBig(vm, " ++ creg x ++ ")"
382doOp v (LTrunc ITBig ITNative) [x] = v ++ "idris_castBigInt(vm, " ++ creg x ++ ")"
383doOp v (LStrInt ITBig) [x] = v ++ "idris_castStrBig(vm, " ++ creg x ++ ")"
384doOp v (LIntStr ITBig) [x] = v ++ "idris_castBigStr(vm, " ++ creg x ++ ")"
385doOp v (LIntStr ITNative) [x] = v ++ "idris_castIntStr(vm, " ++ creg x ++ ")"
386doOp v (LStrInt ITNative) [x] = v ++ "idris_castStrInt(vm, " ++ creg x ++ ")"
387doOp v LFloatStr [x] = v ++ "idris_castFloatStr(vm, " ++ creg x ++ ")"
388doOp v LStrFloat [x] = v ++ "idris_castStrFloat(vm, " ++ creg x ++ ")"
390doOp v LReadStr [x] = v ++ "idris_readStr(vm, GETPTR(" ++ creg x ++ "))"
391doOp _ LPrintNum [x] = "printf(\"%ld\\n\", GETINT(" ++ creg x ++ "))"
392doOp _ LPrintStr [x] = "fputs(GETSTR(" ++ creg x ++ "), stdout)"
394doOp v (LSLt (ATInt (ITFixed ty))) [x, y] = bitOp v "SLt" ty [x, y]
395doOp v (LSLe (ATInt (ITFixed ty))) [x, y] = bitOp v "SLte" ty [x, y]
396doOp v (LEq (ATInt (ITFixed ty))) [x, y] = bitOp v "Eq" ty [x, y]
397doOp v (LSGe (ATInt (ITFixed ty))) [x, y] = bitOp v "SGte" ty [x, y]
398doOp v (LSGt (ATInt (ITFixed ty))) [x, y] = bitOp v "SGt" ty [x, y]
399doOp v (LLt (ITFixed ty)) [x, y] = bitOp v "Lt" ty [x, y]
400doOp v (LLe (ITFixed ty)) [x, y] = bitOp v "Lte" ty [x, y]
401doOp v (LGe (ITFixed ty)) [x, y] = bitOp v "Gte" ty [x, y]
402doOp v (LGt (ITFixed ty)) [x, y] = bitOp v "Gt" ty [x, y]
404doOp v (LSHL (ITFixed ty)) [x, y] = bitOp v "Shl" ty [x, y]
405doOp v (LLSHR (ITFixed ty)) [x, y] = bitOp v "LShr" ty [x, y]
406doOp v (LASHR (ITFixed ty)) [x, y] = bitOp v "AShr" ty [x, y]
407doOp v (LAnd (ITFixed ty)) [x, y] = bitOp v "And" ty [x, y]
408doOp v (LOr (ITFixed ty)) [x, y] = bitOp v "Or" ty [x, y]
409doOp v (LXOr (ITFixed ty)) [x, y] = bitOp v "Xor" ty [x, y]
410doOp v (LCompl (ITFixed ty)) [x] = bitOp v "Compl" ty [x]
412doOp v (LPlus (ATInt (ITFixed ty))) [x, y] = bitOp v "Plus" ty [x, y]
413doOp v (LMinus (ATInt (ITFixed ty))) [x, y] = bitOp v "Minus" ty [x, y]
414doOp v (LTimes (ATInt (ITFixed ty))) [x, y] = bitOp v "Times" ty [x, y]
415doOp v (LUDiv (ITFixed ty)) [x, y] = bitOp v "UDiv" ty [x, y]
416doOp v (LSDiv (ATInt (ITFixed ty))) [x, y] = bitOp v "SDiv" ty [x, y]
417doOp v (LURem (ITFixed ty)) [x, y] = bitOp v "URem" ty [x, y]
418doOp v (LSRem (ATInt (ITFixed ty))) [x, y] = bitOp v "SRem" ty [x, y]
420doOp v (LSExt (ITFixed from) ITBig) [x]
421 = v ++ "MKBIGSI(vm, (" ++ signedTy from ++ ")" ++ creg x ++ "->info.bits" ++ show (nativeTyWidth from) ++ ")"
422doOp v (LSExt ITNative (ITFixed to)) [x]
423 = v ++ "idris_b" ++ show (nativeTyWidth to) ++ "const(vm, GETINT(" ++ creg x ++ "))"
424doOp v (LSExt ITChar (ITFixed to)) [x]
425 = doOp v (LSExt ITNative (ITFixed to)) [x]
426doOp v (LSExt (ITFixed from) ITNative) [x]
427 = v ++ "MKINT((i_int)((" ++ signedTy from ++ ")" ++ creg x ++ "->info.bits" ++ show (nativeTyWidth from) ++ "))"
428doOp v (LSExt (ITFixed from) ITChar) [x]
429 = doOp v (LSExt (ITFixed from) ITNative) [x]
430doOp v (LSExt (ITFixed from) (ITFixed to)) [x]
431 | nativeTyWidth from < nativeTyWidth to = bitCoerce v "S" from to x
432doOp v (LZExt ITNative (ITFixed to)) [x]
433 = v ++ "idris_b" ++ show (nativeTyWidth to) ++ "const(vm, (uintptr_t)GETINT(" ++ creg x ++ ")"
434doOp v (LZExt ITChar (ITFixed to)) [x]
435 = doOp v (LZExt ITNative (ITFixed to)) [x]
436doOp v (LZExt (ITFixed from) ITNative) [x]
437 = v ++ "MKINT((i_int)" ++ creg x ++ "->info.bits" ++ show (nativeTyWidth from) ++ ")"
438doOp v (LZExt (ITFixed from) ITChar) [x]
439 = doOp v (LZExt (ITFixed from) ITNative) [x]
440doOp v (LZExt (ITFixed from) ITBig) [x]
441 = v ++ "MKBIGUI(vm, " ++ creg x ++ "->info.bits" ++ show (nativeTyWidth from) ++ ")"
442doOp v (LZExt ITNative ITBig) [x]
443 = v ++ "MKBIGUI(vm, (uintptr_t)GETINT(" ++ creg x ++ "))"
444doOp v (LZExt (ITFixed from) (ITFixed to)) [x]
445 | nativeTyWidth from < nativeTyWidth to = bitCoerce v "Z" from to x
446doOp v (LTrunc ITNative (ITFixed to)) [x]
447 = v ++ "idris_b" ++ show (nativeTyWidth to) ++ "const(vm, GETINT(" ++ creg x ++ "))"
448doOp v (LTrunc ITChar (ITFixed to)) [x]
449 = doOp v (LTrunc ITNative (ITFixed to)) [x]
450doOp v (LTrunc (ITFixed from) ITNative) [x]
451 = v ++ "MKINT((i_int)" ++ creg x ++ "->info.bits" ++ show (nativeTyWidth from) ++ ")"
452doOp v (LTrunc (ITFixed from) ITChar) [x]
453 = doOp v (LTrunc (ITFixed from) ITNative) [x]
454doOp v (LTrunc ITBig (ITFixed to)) [x]
455 = v ++ "idris_b" ++ show (nativeTyWidth to) ++ "const(vm, ISINT(" ++ creg x ++ ") ? GETINT(" ++ creg x ++ ") : mpz_get_ui(GETMPZ(" ++ creg x ++ ")))"
456doOp v (LTrunc (ITFixed from) (ITFixed to)) [x]
457 | nativeTyWidth from > nativeTyWidth to = bitCoerce v "T" from to x
459doOp v LFExp [x] = v ++ flUnOp "exp" (creg x)
460doOp v LFLog [x] = v ++ flUnOp "log" (creg x)
461doOp v LFSin [x] = v ++ flUnOp "sin" (creg x)
462doOp v LFCos [x] = v ++ flUnOp "cos" (creg x)
463doOp v LFTan [x] = v ++ flUnOp "tan" (creg x)
464doOp v LFASin [x] = v ++ flUnOp "asin" (creg x)
465doOp v LFACos [x] = v ++ flUnOp "acos" (creg x)
466doOp v LFATan [x] = v ++ flUnOp "atan" (creg x)
467doOp v LFSqrt [x] = v ++ flUnOp "sqrt" (creg x)
468doOp v LFFloor [x] = v ++ flUnOp "floor" (creg x)
469doOp v LFCeil [x] = v ++ flUnOp "ceil" (creg x)
471doOp v LStrHead [x] = v ++ "idris_strHead(vm, " ++ creg x ++ ")"
472doOp v LStrTail [x] = v ++ "idris_strTail(vm, " ++ creg x ++ ")"
473doOp v LStrCons [x, y] = v ++ "idris_strCons(vm, " ++ creg x ++ "," ++ creg y ++ ")"
474doOp v LStrIndex [x, y] = v ++ "idris_strIndex(vm, " ++ creg x ++ "," ++ creg y ++ ")"
475doOp v LStrRev [x] = v ++ "idris_strRev(vm, " ++ creg x ++ ")"
477doOp v LAllocate [x] = v ++ "idris_allocate(vm, " ++ creg x ++ ")"
478doOp v LAppendBuffer [a, b, c, d, e, f] = v ++ "idris_appendBuffer(vm, " ++ creg a ++ "," ++ creg b ++ "," ++ creg c ++ "," ++ creg d ++ "," ++ creg e ++ "," ++ creg f ++ ")"
479doOp v (LAppend ity en) [a, b, c, d] = v ++ "idris_append" ++ intTyName ity ++ show en ++ "(vm, " ++ creg a ++ "," ++ creg b ++ "," ++ creg c ++ "," ++ creg d ++ ")"
480doOp v (LPeek ity en) [x, y] = v ++ "idris_peek" ++ intTyName ity ++ show en ++ "(vm, " ++ creg x ++ "," ++ creg y ++ ")"
482doOp v LStdIn [] = v ++ "MKPTR(vm, stdin)"
483doOp v LStdOut [] = v ++ "MKPTR(vm, stdout)"
484doOp v LStdErr [] = v ++ "MKPTR(vm, stderr)"
486doOp v LFork [x] = v ++ "MKPTR(vm, vmThread(vm, " ++ cname (sMN 0 "EVAL") ++ ", " ++ creg x ++ "))"
487doOp v LPar [x] = v ++ creg x -- "MKPTR(vm, vmThread(vm, " ++ cname (MN 0 "EVAL") ++ ", " ++ creg x ++ "))"
488doOp v LVMPtr [] = v ++ "MKPTR(vm, vm)"
489doOp v LNullPtr [] = v ++ "MKPTR(vm, NULL)"
490doOp v LRegisterPtr [p, i] = v ++ "MKMPTR(vm, GETPTR(" ++ creg p ++
491 "), GETINT(" ++ creg i ++ "))"
492doOp v (LChInt ITNative) args = v ++ creg (last args)
493doOp v (LChInt ITChar) args = doOp v (LChInt ITNative) args
494doOp v (LIntCh ITNative) args = v ++ creg (last args)
495doOp v (LIntCh ITChar) args = doOp v (LIntCh ITNative) args
496doOp v LNoOp args = v ++ creg (last args)
497doOp _ op _ = "FAIL /* " ++ show op ++ " */"
499flUnOp :: String -> String -> String
500flUnOp name val = "MKFLOAT(vm, " ++ name ++ "(GETFLOAT(" ++ val ++ ")))"