diff options
author | Camil Staps | 2018-12-24 14:15:16 +0100 |
---|---|---|
committer | Camil Staps | 2018-12-24 14:15:16 +0100 |
commit | f31b200b58e994b7505707931d4278e3f61cc2d6 (patch) | |
tree | 372f4c08e9d35751a205ac965acc7385ff0c207c | |
parent | Use rcx as scratch register, since it is caller-saved in the System V and Mic... (diff) |
Iterative development
-rw-r--r-- | sjit.icl | 174 | ||||
-rw-r--r-- | sjit_c.c | 35 |
2 files changed, 151 insertions, 58 deletions
@@ -3,6 +3,7 @@ module sjit import StdEnv import StdGeneric import StdMaybe +import StdOverloadedList from Data.Func import mapSt, $ from Data.Map import :: Map(..), get, put, newMap, fromList @@ -39,28 +40,104 @@ import code from "sjit_c." :: Program :== {!Instr} :: CompileState = - { vars :: !Map String Int - , funs :: !Map String Int - , sp :: !Int - , pc :: !Int + { vars :: !Map String Int + , funs :: !Map String Int + , sp :: !Int + , pc :: !Int + , blocks :: ![!Program!] + , jitst :: !JITState } -compile :: ![Function] -> Program -compile funs +:: JITState = + { n_instr :: !Int + , code_start :: !Int + , code_len :: !Int + , code_ptr :: !Int + , mapping :: !Int + } + +appendProgram :: !Bool !Program !JITState -> JITState +appendProgram is_main prog jitst +# new_code_ptr = append + jitst.code_start jitst.code_len jitst.code_ptr + jitst.mapping + jitst.n_instr + (encode prog) + is_main += + { jitst + & code_ptr = new_code_ptr + , n_instr = jitst.n_instr + size prog + } +where + append :: !Int !Int !Int !Int !Int !{#Int} !Bool -> Int + append _ _ _ _ _ _ _ = code { + ccall jit_append "pIppIAI:p" + } + +bootstrap :: (!Program, !CompileState) +bootstrap # (len_bs, bs_funs) = bootstrap_funs -# (is,cs) = mapSt fun funs {vars=newMap, funs=fromList bs_funs, sp=0, pc=len_bs} -= case get "main" cs.funs of - Nothing -> abort "no main function\n" - Just m - # bs = bootstrap m - -> {i \\ i <- flatten [is \\ (_,is) <- bs] ++ flatten is} +# is = {i \\ i <- flatten [is \\ (_,is) <- header]} += + ( is, + { vars = newMap + , funs = fromList bs_funs + , sp = 0 + , pc = len_bs + , blocks = [!is!] + , jitst = appendProgram False is (initJITState 1000) + }) where - fun :: !Function !CompileState -> (![Instr], !CompileState) - fun f cs - # cs & funs = put f.fun_name cs.pc cs.funs - # (is,cs) = expr f.fun_expr cs - = (reverse [Ret:is], {cs & pc=cs.pc+1}) + bootstrap_funs :: (!Int, ![(String, Int)]) + bootstrap_funs = iter 0 header + where + iter :: !Int ![(String, [Instr])] -> (!Int, ![(String, Int)]) + iter pc [] = (pc, []) + iter pc [(name,is):rest] + # fun = (name,pc) + # (pc,funs) = iter (pc+length is) rest + = (pc,[fun:funs]) + + header :: [(!String, ![Instr])] + header = + [ ("_", [PushI 0,Call 0 /* main address */,Halt]) + , ("+", [IAddRet]) + , ("*", [IMulRet]) + , ("-", [ISubRet]) + , ("/", [IDivRet]) + ] + initJITState :: !Int -> JITState + initJITState maxlen + # (code_start,mapping) = init maxlen (maxlen*10) + = + { n_instr = 0 + , code_start = code_start + , code_len = maxlen*10 + , code_ptr = code_start + , mapping = mapping + } + where + init :: !Int !Int -> (!Int, !Int) + init _ _ = code { + ccall init_jit "II:Vpp" + } + +compile :: !Function !CompileState -> CompileState +compile f cs +# cs & funs = put f.fun_name cs.pc cs.funs +# vars = cs.vars +# (is,cs) = expr f.fun_expr {cs & vars=newMap} +# is = {i \\ i <- reverse [Ret:is]} += + { cs + & vars = vars + , pc = cs.pc+1 + , blocks = cs.blocks ++| [!is!] + , jitst = appendProgram (f.fun_name == "main") is cs.jitst + } +where expr :: !Expr !CompileState -> (![Instr], !CompileState) expr (Int i) cs = ([PushI i], {cs & sp=cs.sp+1, pc=cs.pc+1}) expr (Var v) cs = case get v cs.vars of @@ -76,28 +153,17 @@ where # (is,cs) = expr e cs = ([Put (max 1 (length vs)+1):is], {cs & sp=cs.sp-1, pc=cs.pc+1}) - bootstrap_funs :: (!Int, ![(String, Int)]) - bootstrap_funs = iter 0 (bootstrap 0) - where - iter :: !Int ![(String, [Instr])] -> (!Int, ![(String, Int)]) - iter pc [] = (pc, []) - iter pc [(name,is):rest] - # fun = (name,pc) - # (pc,funs) = iter (pc+length is) rest - = (pc,[fun:funs]) - - bootstrap :: !Int -> [(String, [Instr])] - bootstrap main = - [ ("_", [PushI 0,Call main,Halt]) - , ("+", [IAddRet]) - , ("*", [IMulRet]) - , ("-", [ISubRet]) - , ("/", [IDivRet]) - ] +compile_all :: !(Maybe CompileState) ![Function] -> CompileState +compile_all mcs funs +# cs = case mcs of + Just cs -> cs + Nothing -> snd bootstrap += foldl (flip compile) cs funs -exec :: !Program -> Int -exec prog = exec 0 [] +interpret :: !CompileState -> Int +interpret cs = exec 0 [] where + prog = get_program cs sz = size prog exec :: !Int ![Int] -> Int @@ -125,6 +191,22 @@ where IDivRet -> case stack of [ret:a:b:stack] -> exec ret [a:a/b:stack] + get_program :: !CompileState -> Program + get_program cs + # prog = loop 0 cs.blocks (createArray (sum [size b \\ b <|- cs.blocks]) Halt) + # prog & [1] = Call (fromJust (get "main" cs.funs)) + = prog + where + loop :: !Int ![!Program!] !*Program -> .Program + loop i [!b:bs!] prog + # (i,prog) = copy i 0 (size b-1) b prog + = loop i bs prog + where + copy :: !Int !Int !Int !Program !*Program -> *(!Int, !*Program) + copy i _ -1 _ prog = (i, prog) + copy i bi n b prog = copy (i+1) (bi+1) (n-1) b {prog & [i]=b.[bi]} + loop _ [!!] prog = prog + generic gEncodedSize a :: !a -> Int gEncodedSize{|Int|} _ = 1 gEncodedSize{|{!}|} fx xs = 1 + sum [fx x \\ x <-: xs] @@ -163,12 +245,12 @@ encode x # (_,arr) = gEncode{|*|} x 0 (createArray (gEncodedSize{|*|} x) -1) = arr -jit :: !Program -> Int -jit prog = jit (encode prog) +exec :: !CompileState -> Int +exec {jitst} = exec jitst.code_start where - jit :: !*{#Int} -> Int - jit _ = code { - ccall jit "A:I" + exec :: !Int -> Int + exec _ = code { + ccall jit_exec "p:I" } import Text.GenPrint @@ -176,16 +258,16 @@ derive gPrint Instr Start w # (io,w) = stdio w -# io = io <<< "Program: " <<< printToString prog <<< "\n" +# io = Foldl (\io b -> io <<< " " <<< printToString b <<< "\n") (io <<< "Program blocks:\n") comp_state.blocks # io = io <<< "Interpreted result: " <<< interpreted_result <<< "\n" # io = io <<< "JIT-compiled result: " <<< jit_compiled_result <<< "\n" # (_,w) = fclose io w = setReturnCode (if (interpreted_result==jit_compiled_result) 0 1) w where - interpreted_result = exec prog - jit_compiled_result = jit prog + interpreted_result = interpret comp_state + jit_compiled_result = exec comp_state -prog =: compile +comp_state =: compile_all Nothing [ {fun_name="id", fun_expr=Abstr ["x"] (Var "x")} , {fun_name="const", fun_expr=Abstr ["x","y"] (Var "x")} , {fun_name="main", fun_expr=Abstr [] (App "+" [App "const" [Int 37, Int 10], App "const" [Int 5, Int 10]])} @@ -106,7 +106,7 @@ static inline void gen_instr(char *full_code, char **code_p, uint64_t **pgm_p, u case Call: arg=pgm[1]; #ifdef DEBUG_JIT_INSTRUCTIONS - fprintf(stderr,"Call %lu -> %d\n",arg,mapping[arg]-(&code[5]-full_code)); + fprintf(stderr,"Call %lu -> %d\n",arg,mapping[arg]-(uint32_t)(&code[5]-full_code)); #endif code[0]='\xe8'; /* callq ARG */ *(uint32_t*)&code[1]=mapping[arg]-(&code[5]-full_code); @@ -181,15 +181,20 @@ static inline void gen_instr(char *full_code, char **code_p, uint64_t **pgm_p, u *pgm_p=pgm; } -unsigned int jit(uint64_t *pgm) { +void init_jit(uint64_t max_instrs, uint64_t max_code_len, + char **code_block, uint32_t **mapping) { + *code_block=mmap (NULL,max_code_len,PROT_READ | PROT_EXEC,MAP_ANONYMOUS | MAP_PRIVATE,0,0); + *mapping=malloc (max_instrs*sizeof(uint32_t)); +} + +char *jit_append(char *code_block, uint32_t code_len, char *code_ptr, + uint32_t *mapping, uint32_t n_instr, uint64_t *pgm, int is_main) { uint32_t len=*pgm++; uint32_t i; - - uint32_t *mapping=malloc(len*sizeof(uint32_t)); - uint32_t code_i=0; + uint32_t code_i=code_ptr-code_block; uint64_t *pgm_p=pgm; - for (i=0; i<len; i++) { + for (i=n_instr; i<n_instr+len; i++) { enum instr instr=(enum instr)*pgm_p; mapping[i]=code_i; @@ -209,14 +214,20 @@ unsigned int jit(uint64_t *pgm) { } } - char *code=mmap(NULL, code_i, PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); - char *code_wr=code; + mprotect (code_block,code_len,PROT_WRITE); + + if (is_main) + *(uint32_t*)&code_block[9]=code_ptr-code_block-13; + pgm_p=pgm; for (i=0; i<len; i++) - gen_instr(code, &code_wr, &pgm_p, mapping); + gen_instr (code_block,&code_ptr,&pgm_p,mapping); + + mprotect (code_block,code_len,PROT_READ | PROT_EXEC); - mprotect(code, code_i, PROT_READ | PROT_EXEC); - int (*fun)(void) = (int(*)(void)) code; + return code_ptr; +} - return fun(); +uint64_t jit_exec(char *code_block) { + return ((uint64_t(*)(void))code_block)(); } |