diff --git a/.gitignore b/.gitignore index e0a90a616458144f6a50e14980bc66911eeac522..42765851f67e460d370e8baed8a80bb4998717c3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,53 +1,9 @@ -tests/**/*.ast -tests/**/*.cfg -tests/**/*.cfg0 -tests/**/*.cfg1 -tests/**/*.cfg2 -tests/**/*.cfg3 -tests/**/*.e.dump -tests/**/*.e.html -tests/**/*.exe -tests/**/*.json -tests/**/*.lex -tests/**/*.linear -tests/**/*.linear1 -tests/**/*.ltl -tests/**/*.rig -tests/**/*.rtl -tests/**/*.s -tests/**/*.svg -tests/results.html -tests/__pycache__ src/_build -alpaga/_build grammar.html src/generated_parser.ml src/config.ml **/*.native -alpaga/ml_parser_generator -alpaga/alpaga -alpaga/ml_parser_generator.native -tykernel/*.ast -tykernel/*.cfg -tykernel/*.cfg0 -tykernel/*.cfg1 -tykernel/*.cfg2 -tykernel/*.e.dump -tykernel/*.e.html -tykernel/*.exe -tykernel/*.lex -tykernel/*.linear -tykernel/*.linear1 -tykernel/*.ltl -tykernel/*.rtl -tykernel/*.s -tykernel/*.svg skeleton -sujet/_minted-tp -sujet/*.aux -sujet/*.fdb_latexmk -sujet/*.fls -sujet/*.log -sujet/*.out -sujet/*.pdf -sujet/*.synctex.gz +src/.vscode/ +.vscode/ +Makefile.config \ No newline at end of file diff --git a/Makefile b/Makefile index 1cac3804801bbfad3bd8f9844b2e2217cdaf3fc1..413254d16f14a82cc0f073a5d7b718366b1d26c9 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,19 @@ all: main.native .PHONY: main.native -main.native: + +src/config.ml: configure + ./configure + +main.native: src/config.ml make -C alpaga ./alpaga/alpaga \ -g expr_grammar_action.g \ -pml src/generated_parser.ml \ -t grammar.html - ./configure make -C src ln -sf src/main.native main.native - clean: make -C alpaga clean rm -f src/generated_parser.ml diff --git a/Sujet.pdf b/Sujet.pdf index 3f1222d0362a2e74c1a5e13ded8a8368fb4d15e8..c0f06c0fb79bd3db8474acf83339bd618ec2783a 100644 Binary files a/Sujet.pdf and b/Sujet.pdf differ diff --git a/alpaga/ml_parser_generator.ml b/alpaga/ml_parser_generator.ml index 01a8a705f9e87a9d827ed34c180a97d48961e7bf..4b0c6d8b92ffd987ed756f488dc5a4de6ab4414d 100644 --- a/alpaga/ml_parser_generator.ml +++ b/alpaga/ml_parser_generator.ml @@ -68,7 +68,8 @@ let make_nt (table: string*string -> lltype list) (toks,nts,rules) oc n () = ) (a::r); Printf.fprintf oc "Printf.sprintf \"}\" ^ \n" end; - Printf.fprintf oc " Printf.sprintf \" but got '%%s' instead.\\n\" got\n"; + Printf.fprintf oc " Printf.sprintf \" but got '%%s' instead.\\n\" got\n ^ "; + Printf.fprintf oc " Printf.sprintf \" '%%s' \\n\" (String.concat \",\" (List.map (fun (x, _) -> string_of_symbol x) (List.take 10 tokens)))\n"; Printf.fprintf oc " )"; Printf.fprintf oc "\n end\n\n" diff --git a/configure b/configure index 8e49ee87b4aa6aa5be7987eb0984158907672ef4..42d40d9cc10cf698bc80e95bad227a1d5a6ab5e3 100755 --- a/configure +++ b/configure @@ -2,5 +2,16 @@ RUNTIME=$(pwd)/runtime +RVAS=$(which -a riscv64-unknown-linux-gnu-as riscv64-unknown-elf-as riscv64-linux-gnu-as 2>/dev/null | grep -v "not found" | head -n1) +RVLD=$(which -a riscv64-unknown-linux-gnu-ld riscv64-unknown-elf-ld riscv64-linux-gnu-ld 2>/dev/null | grep -v "not found" | head -n1) +QEMU32=$(which -a qemu-riscv32-static 2>/dev/null | grep -v "not found" | head -n1) +QEMU64=$(which -a qemu-riscv64-static 2>/dev/null | grep -v "not found" | head -n1) + + echo "let runtime_dir = \"${RUNTIME}\"" > src/config.ml -echo "let qemu_path = \"/usr/local/bin/qemu-riscv\"" >> src/config.ml +echo "let qemu32 = \"${QEMU32}\"" >> src/config.ml +echo "let qemu64 = \"${QEMU64}\"" >> src/config.ml +echo "let rv_as = \"${RVAS}\"" >> src/config.ml +echo "let rv_ld = \"${RVLD}\"" >> src/config.ml +echo "let os_target = \"linux\"" >> src/config.ml + diff --git a/ldb/ldb.html b/ldb/ldb.html index f4fea01ffa82c0dd73e622a183989d993d60edd6..efcdd8ee2bdf96ca51cd686745a0371b478831ba 100644 --- a/ldb/ldb.html +++ b/ldb/ldb.html @@ -44,7 +44,7 @@ <div id="memstate"></div> </div> <div id="expr"> - <input type="text" id="expr_input" size="30" /><br> + <input type="text" id="expr_input" size="20" /><br> Result: <span id="expr_res"></span><hr> <div id="subexprs"></div> </div> diff --git a/ldb/ldb.js b/ldb/ldb.js index a5709d16485e8a23834b925be881d93e66e9b42b..a1320381695f964ed4ea0cef96816545749e3082 100644 --- a/ldb/ldb.js +++ b/ldb/ldb.js @@ -678,10 +678,10 @@ function handle_command(d){ for(let [evar,loc] of Object.entries(fb['vars'])){ if(Object.keys(loc).includes("reg")){ - p.insert("span").html("Var "+evar+": "+loc["reg"]) + p.insert("span").html("Var "+evar+": Reg "+loc["reg"]) .insert("br"); } else { - p.insert("span").html("Var "+evar+": "+loc["stk"]) + p.insert("span").html("Var "+evar+": Stk "+loc["stk"]) .insert("br"); } } diff --git a/ldb/style.css b/ldb/style.css index 3828332e4203f7ece26d1fc1f40eeb03f275f631..036b6c9856d48022239e634c21d7925bdd9e9b86 100644 --- a/ldb/style.css +++ b/ldb/style.css @@ -54,7 +54,7 @@ html { } #body{ display: grid; - grid-template-columns: [ctrl] 300px [code] 250px [outcfg] 600px [state] 700px; + grid-template-columns: [ctrl] 250px [code] 400px [outcfg] 500px [state] 700px; grid-template-rows: [row1] 200px [row2] 200px [row3] 400px [row4]; } #code { diff --git a/runtime/lib32.s b/runtime/lib32.s index e5ad73a5bb14f27d11322752602d5e8180f90fa0..1249dd2695e39b72383836cf596e32c41fca1bf5 100644 --- a/runtime/lib32.s +++ b/runtime/lib32.s @@ -1,3 +1,4 @@ + .include "syscall_numbers.s" .global atoi .global print_int .global println @@ -66,7 +67,7 @@ li a3, 0 li a4, 0 li a5, 0 li a6, 0 -li a7, 64 +li a7, SYSCALL_WRITE ecall jr ra print_char: diff --git a/runtime/lib64.s b/runtime/lib64.s index f407f9da3dff0a64590d61a11717054ed298f607..8a4710e71379bfcf163554cbd98dfbb4c718d25e 100644 --- a/runtime/lib64.s +++ b/runtime/lib64.s @@ -1,3 +1,4 @@ +.include "syscall_numbers.s" .global atoi .global print_int .global println @@ -55,6 +56,7 @@ jal ra, print_a1 ld ra, 0(sp) addi sp, sp, 8 jr ra + print_a1: addi sp, sp, -8 sd ra,0(sp) @@ -68,9 +70,10 @@ li a3, 0 li a4, 0 li a5, 0 li a6, 0 -li a7, 64 +li a7, SYSCALL_WRITE ecall jr ra + print_char: addi sp, sp, -8 sd ra, 0(sp) diff --git a/src/Makefile b/src/Makefile index f972d566c1f3d4468cb26cd3d8c829265a4efe72..94e5b1b038cd1a3184de3bb2016872cd86755b61 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,11 +1,11 @@ SRC=archi.ml ast.ml builtins.ml config.ml cfg_constprop.ml cfg_dead_assign.ml \ -cfg.ml cfg_print.ml cfg_gen.ml cfg_liveness.ml cfg_loops.ml cfg_nop_elim.ml \ -cfg_run.ml elang.ml elang_print.ml elang_gen.ml elang_run.ml e_regexp.ml \ +cfg.ml cfg_print.ml cfg_gen.ml cfg_liveness.ml cfg_nop_elim.ml cfg_run.ml \ +elang.ml elang_print.ml elang_gen.ml elang_run.ml e_regexp.ml \ generated_parser.ml lexer_generator.ml linear_dse.ml linear_liveness.ml \ linear.ml linear_print.ml linear_gen.ml linear_run.ml ltl.ml ltl_print.ml \ ltl_gen.ml ltl_run.ml ltl_debug.ml main.ml options.ml parser.ml prog.ml \ regalloc.ml report.ml riscv.ml rtl.ml rtl_print.ml rtl_gen.ml rtl_run.ml \ -symbols.ml utils.ml +symbols.ml tokenize.ml utils.ml TG = main.native diff --git a/src/archi.ml b/src/archi.ml index b65dc347734eb5a8f70b752557906564f5f4c1ea..988790064fc6218be79355941aaed39e8ed720ab 100644 --- a/src/archi.ml +++ b/src/archi.ml @@ -1,29 +1,61 @@ +open Config + type archi = A64 | A32 -let wordsize = ref 8 -let assembler = ref "riscv64-unknown-elf-gcc" -let instrsuffix = ref 'd' let archi = ref A64 -let nbits = ref 64 +let nbits () = + match !archi with + | A64 -> 64 + | A32 -> 32 + +let wordsize () = nbits () / 8 + +let assembler () = + let opts = + match !archi with + | A64 -> "-march=rv64imafdc -mabi=lp64d" + | A32 -> "-march=rv32imafdc -mabi=ilp32" + in + Format.sprintf "%s %s" Config.rv_as opts + +let linker () = + let opts = + match !archi with + A64 -> "-melf64lriscv" + | A32 -> "-melf32lriscv" + in + Format.sprintf "%s %s" Config.rv_ld opts + +let instrsuffix () = + match !archi with + | A64 -> 'd' + | A32 -> 'w' + +let qemu () = + match !archi with + | A64 -> Config.qemu64 + | A32 -> Config.qemu32 let heapstart = ref 8 -let init_archi a () = - begin match a with - | A64 -> - begin - wordsize := 8; - assembler := "riscv64-unknown-elf-gcc"; - instrsuffix := 'd'; - archi := A64; - end - | A32 -> - begin - wordsize := 4; - assembler := "riscv32-unknown-elf-gcc"; - instrsuffix := 'w'; - archi := A32; - end - end - ; - nbits := !wordsize *8; +type target_system = + | Linux + | Xv6 + +let target = ref Linux + +let lib_syscall () = + match !target with + | Linux -> "linux" + | Xv6 -> "xv6" + +let target_data_segment t = + match t with + | Linux -> "8000000" + | Xv6 -> "2000" + +let runtime_lib_include_path () = + Format.sprintf "%s/%s" Config.runtime_dir (lib_syscall ()) + +let runtime_lib_path () = + Format.sprintf "%s/lib%d.s" Config.runtime_dir (nbits ()) diff --git a/src/cfg_constprop.ml b/src/cfg_constprop.ml index 524f8b1f4d6e67cbd5da16c2461a652e5953ab66..55440c63ee32a4817c641659b92670c3c0abceee 100644 --- a/src/cfg_constprop.ml +++ b/src/cfg_constprop.ml @@ -3,6 +3,9 @@ open Cfg open Elang_run open Prog open Utils +open Report +open Cfg_print +open Options (* [simple_eval_eexpr e] evaluates an expression [e] with no variables. Raises an exception if the expression contains variables. *) @@ -46,3 +49,10 @@ let constant_propagation_gdef = function let constant_propagation p = assoc_map constant_propagation_gdef p + +let pass_constant_propagation p = + let cfg = constant_propagation p in + record_compile_result "Constprop"; + dump (!cfg_dump >*> fun s -> s ^ "1") dump_cfg_prog cfg + (call_dot "cfg-after-cstprop" "CFG after Constant Propagation"); + OK cfg diff --git a/src/cfg_dead_assign.ml b/src/cfg_dead_assign.ml index abd0f0420c56af9dfa4408246744c514dce57d8c..e319094bc62d967d2cdbff918bb0e7d8d2e2aa64 100644 --- a/src/cfg_dead_assign.ml +++ b/src/cfg_dead_assign.ml @@ -3,6 +3,9 @@ open Cfg open Prog open Utils open Cfg_liveness +open Report +open Cfg_print +open Options (* Dead Assign Elimination -- Élimination des affectations mortes *) @@ -32,3 +35,10 @@ let dead_assign_elimination_gdef = function let dead_assign_elimination p = assoc_map dead_assign_elimination_gdef p + +let pass_dead_assign_elimination cfg = + let cfg = dead_assign_elimination cfg in + record_compile_result "DeadAssign"; + dump (!cfg_dump >*> fun s -> s ^ "2") dump_cfg_prog cfg + (call_dot "cfg-after-dae" "CFG after DAE"); + OK cfg diff --git a/src/cfg_gen.ml b/src/cfg_gen.ml index e3d6b17c3aa8443830e453164d0e0067787acbd5..b20b93392d02bcde3a7e0a8f599991289fd51f54 100644 --- a/src/cfg_gen.ml +++ b/src/cfg_gen.ml @@ -3,6 +3,9 @@ open Elang open Cfg open Utils open Prog +open Report +open Cfg_print +open Options (* [cfg_expr_of_eexpr e] converts an [Elang.expr] into a [expr res]. This should always succeed and be straightforward. @@ -104,3 +107,12 @@ let cfg_gdef_of_edef gd = let cfg_prog_of_eprog (ep: eprog) : cfg_fun prog res = assoc_map_res (fun fname -> cfg_gdef_of_edef) ep + +let pass_cfg_gen ep = + match cfg_prog_of_eprog ep with + | Error msg -> + record_compile_result ~error:(Some msg) "CFG"; Error msg + | OK cfg -> + record_compile_result "CFG"; + dump !cfg_dump dump_cfg_prog cfg (call_dot "cfg" "CFG"); + OK cfg diff --git a/src/cfg_nop_elim.ml b/src/cfg_nop_elim.ml index 9de89ece4322c73f0282b39c0d55b1c74242b98d..aae822522f4fb120370e58b9a32f93c5383a3b74 100644 --- a/src/cfg_nop_elim.ml +++ b/src/cfg_nop_elim.ml @@ -3,6 +3,9 @@ open Batteries open Prog open Utils open Cfg +open Report +open Cfg_print +open Options (* Élimination des NOPs. *) @@ -77,3 +80,11 @@ let nop_elim_gdef gd = let nop_elimination cp = assoc_map nop_elim_gdef cp + + +let pass_nop_elimination cfg = + let cfg = nop_elimination cfg in + record_compile_result "NopElim"; + dump (!cfg_dump >*> fun s -> s ^ "3") dump_cfg_prog cfg + (call_dot "cfg-after-nop" "CFG after NOP elim"); + OK cfg diff --git a/src/elang_gen.ml b/src/elang_gen.ml index e8f9cd6922ac226fc7496be037d92ae7f351f476..eb6615b109ae955bbfacc6f310fa77caf1a3325b 100644 --- a/src/elang_gen.ml +++ b/src/elang_gen.ml @@ -2,6 +2,9 @@ open Ast open Elang open Prog open Utils +open Report +open Elang_print +open Options let tag_is_binop = function @@ -86,3 +89,13 @@ let make_eprog_of_ast (a: tree) : eprog res = | _ -> Error (Printf.sprintf "make_fundef_of_ast: Expected a Tlistglobdef, got %s." (string_of_ast a)) + +let pass_elang ast = + match make_eprog_of_ast ast with + | Error msg -> + record_compile_result ~error:(Some msg) "Elang"; + Error msg + | OK ep -> + dump !e_dump dump_e ep (fun file () -> + add_to_report "e" "E" (Code (file_contents file))); OK ep + diff --git a/src/lexer_generator.ml b/src/lexer_generator.ml index bd37e8489758ca694c62dbb7fa5063f2fa7c57b5..f79e1dbf2bf4305a159b886dc73cb407b5ded0ac 100644 --- a/src/lexer_generator.ml +++ b/src/lexer_generator.ml @@ -63,7 +63,7 @@ let star_nfa n t = (* [nfa_of_regexp r freshstate t] construit un NFA qui reconnaît le même langage que l'expression régulière [r]. [freshstate] correspond à un entier pour lequel il n'y a pas encore d'état dans - le nfa. Il suffit d'incrémenter [freshstate] pour obtenir de nouveaux état non utilisés. + le nfa. Il suffit d'incrémenter [freshstate] pour obtenir de nouveaux états non utilisés. [t] est une fonction du type [string -> token option] utile pour les état finaux. *) let rec nfa_of_regexp r freshstate t = @@ -447,11 +447,6 @@ let dfa_to_dot oc (n : dfa) (cl: char list): unit = ) n.dfa_states; Printf.fprintf oc "}\n" -let alts l = - match l with - [] -> Eps - | a::r -> List.fold_left (fun acc r -> Alt(acc,r)) a l - let nfa_of_list_regexp l = let (n, fs) = List.fold_left (fun (nfa, fs) (r,t) -> let n,fs = nfa_of_regexp r fs t in diff --git a/src/linear_dse.ml b/src/linear_dse.ml index 1f4e0e0a1e893c7d623881aea3f893469543016a..e0ac6d97bf1576b80f8390ccc96b14342cc7cf96 100644 --- a/src/linear_dse.ml +++ b/src/linear_dse.ml @@ -5,6 +5,9 @@ open Batteries open BatList open Prog open Utils +open Report +open Linear_print +open Options let dse_instr (ins: rtl_instr) live = [ins] @@ -26,3 +29,12 @@ let dse_prog p live = let f = dse_fun live f in (fname, Gfun f) ) p + +let pass_linear_dse linear lives = + let linear = dse_prog linear lives in + record_compile_result "DSE"; + dump (!linear_dump >*> fun s -> s ^ "1") + (fun oc -> dump_linear_prog oc (Some lives)) linear + (fun file () -> add_to_report "linear-after-dse" "Linear after DSE" + (Code (file_contents file))); + OK linear diff --git a/src/linear_gen.ml b/src/linear_gen.ml index 8c049a3ce341f532d347c10a8cf7b766e0a76ad1..c12bd04588cfef6a06de11d299bd2ebcd26c09c3 100644 --- a/src/linear_gen.ml +++ b/src/linear_gen.ml @@ -3,7 +3,10 @@ open Rtl open Linear open Prog open Utils - +open Report +open Linear_print +open Options +open Linear_liveness let succs_of_rtl_instr (i: rtl_instr) = match i with @@ -55,3 +58,10 @@ let linear_of_rtl_gdef = function let linear_of_rtl r = assoc_map linear_of_rtl_gdef r + +let pass_linearize rtl = + let linear = linear_of_rtl rtl in + let lives = liveness_linear_prog linear in + dump !linear_dump (fun oc -> dump_linear_prog oc (Some lives)) linear + (fun file () -> add_to_report "linear" "Linear" (Code (file_contents file))); + OK (linear, lives) diff --git a/src/ltl.ml b/src/ltl.ml index a1344a5b960ae72516df1c6251bb15173a1cd8af..6082bfb5b45f4a311e6c8a681e20676c5509c3a9 100644 --- a/src/ltl.ml +++ b/src/ltl.ml @@ -53,10 +53,10 @@ let reg_ret = reg_a0 type ltl_instr = LAddi of ltl_reg * ltl_reg * int | LSubi of ltl_reg * ltl_reg * int - | LStore of ltl_reg * int * ltl_reg * int (* LStore(rd, rofs, rs, sz) : store + | LStore of ltl_reg * int * ltl_reg * mem_access_size (* LStore(rd, rofs, rs, sz) : store value in [rs] on [sz] bytes at address [rd+rofs] *) - | LLoad of ltl_reg * ltl_reg * int * int (* LLoad(rd, rs, rofs, sz) : load + | LLoad of ltl_reg * ltl_reg * int * mem_access_size (* LLoad(rd, rs, rofs, sz) : load value at address [rs+rofs] on [sz] bytes in register [rd]. *) | LMov of ltl_reg * ltl_reg (* LMov(rd, rs) : move value of [rs] into [rd]. diff --git a/src/ltl_gen.ml b/src/ltl_gen.ml index 68fb1e7de8184a903b30ce3c0227e0de4faeb932..06edd325206226d5cfb63a11d9fcd6e3ace70c27 100644 --- a/src/ltl_gen.ml +++ b/src/ltl_gen.ml @@ -7,6 +7,8 @@ open Prog open Utils open Regalloc open Linear_liveness +open Report +open Options (* list of registers used to store arguments. [a0-a7] *) let arg_registers = @@ -18,12 +20,12 @@ let arg_registers = *) let make_push r = - [LSubi(reg_sp, reg_sp, !Archi.wordsize); - LStore(reg_sp, 0, r, !Archi.wordsize)] + [LSubi(reg_sp, reg_sp, (Archi.wordsize ())); + LStore(reg_sp, 0, r, (archi_mas ()))] let make_pop r = - [LLoad(r, reg_sp, 0, !Archi.wordsize); - LAddi(reg_sp, reg_sp, !Archi.wordsize)] + [LLoad(r, reg_sp, 0, (archi_mas ())); + LAddi(reg_sp, reg_sp, (Archi.wordsize ()))] let make_sp_sub v = [LSubi(reg_sp, reg_sp, v)] @@ -39,12 +41,12 @@ let make_loc_mov src dst = match src, dst with | Stk osrc , Stk odst -> let rtmp = reg_tmp1 in - [LLoad(rtmp, reg_fp, !Archi.wordsize * osrc, !Archi.wordsize); - LStore(reg_fp, !Archi.wordsize * odst, rtmp, !Archi.wordsize)] + [LLoad(rtmp, reg_fp, (Archi.wordsize ()) * osrc, (archi_mas ())); + LStore(reg_fp, (Archi.wordsize ()) * odst, rtmp, (archi_mas ()))] | Stk osrc, Reg rdst -> - [LLoad(rdst, reg_fp, !Archi.wordsize * osrc, !Archi.wordsize)] + [LLoad(rdst, reg_fp, (Archi.wordsize ()) * osrc, (archi_mas ()))] | Reg rsrc, Stk ofst -> - [LStore(reg_fp, !Archi.wordsize * ofst, rsrc, !Archi.wordsize)] + [LStore(reg_fp, (Archi.wordsize ()) * ofst, rsrc, (archi_mas ()))] | Reg rsrc, Reg rdst -> [LMov(rdst,rsrc)] @@ -54,7 +56,7 @@ let load_loc tmp allocation r = match Hashtbl.find_option allocation r with | None -> Error (Format.sprintf "Unable to allocate RTL register r%d." r) - | Some (Stk o) -> OK ([LLoad(tmp, reg_fp, !Archi.wordsize * o, !Archi.wordsize)], tmp) + | Some (Stk o) -> OK ([LLoad(tmp, reg_fp, (Archi.wordsize ()) * o, (archi_mas ()))], tmp) | Some (Reg r) -> OK ([], r) (* store_loc tmp allocation r = (l, r'). I want to write in RTL register r. @@ -63,7 +65,7 @@ let store_loc tmp allocation r = match Hashtbl.find_option allocation r with | None -> Error (Format.sprintf "Unable to allocate RTL register r%d." r) - | Some (Stk o) -> OK ([LStore(reg_fp, !Archi.wordsize * o, tmp, !Archi.wordsize)], tmp) + | Some (Stk o) -> OK ([LStore(reg_fp, (Archi.wordsize ()) * o, tmp, (archi_mas ()))], tmp) | Some (Reg r) -> OK ([], r) (* saves registers in [to_save] on the stack at offsets [fp + 8 * o, fp + 8 * (o @@ -73,14 +75,14 @@ let store_loc tmp allocation r = - the list of store instructions - the next offset to be written. *) let save_caller_save to_save ofs = List.fold_left (fun (instrs, arg_saved, ofs) reg -> - (instrs @ [LStore(reg_fp, !Archi.wordsize * ofs, reg, !Archi.wordsize)], + (instrs @ [LStore(reg_fp, (Archi.wordsize ()) * ofs, reg, (archi_mas ()))], (reg,ofs)::arg_saved, ofs - 1) ) ([], [], ofs) to_save (* Given a list [(reg,ofs)], loads [fp+ofs] into [reg]. *) let restore_caller_save arg_saved = List.map - (fun (reg, ofs) -> LLoad(reg, reg_fp, !Archi.wordsize * ofs, !Archi.wordsize)) + (fun (reg, ofs) -> LLoad(reg, reg_fp, (Archi.wordsize ()) * ofs, (archi_mas ()))) arg_saved let num_parameters_passed_on_stack regs = @@ -192,13 +194,13 @@ let pass_parameters rargs allocation arg_saved = begin match src with | Reg rs -> (rd::overwritten, [LMov(rd, rs)],[], npush) | Stk o -> (rd::overwritten, - [LLoad(rd, reg_fp, !Archi.wordsize * o, !Archi.wordsize)], + [LLoad(rd, reg_fp, (Archi.wordsize ()) * o, (archi_mas ()))], [], npush) end else begin match src with | Reg rs -> (overwritten, [], make_push rs@pushes, npush+1) | Stk o -> (overwritten, [], - LLoad(reg_tmp1, reg_fp, !Archi.wordsize * o, !Archi.wordsize) + LLoad(reg_tmp1, reg_fp, (Archi.wordsize ()) * o, (archi_mas ())) ::make_push reg_tmp1 @ pushes, npush+1) end @@ -307,11 +309,11 @@ let ltl_instrs_of_linear_instr fname live_out allocation match Hashtbl.find_option allocation r with | None -> Error (Format.sprintf "Could not find allocation for register %d\n" r) | Some (Reg rs) -> OK [LMov(reg_a0, rs)] - | Some (Stk o) -> OK [LLoad(reg_a0, reg_fp, !Archi.wordsize * o, !Archi.wordsize)] + | Some (Stk o) -> OK [LLoad(reg_a0, reg_fp, (Archi.wordsize ()) * o, (archi_mas ()))] in parameter_passing >>= fun parameter_passing -> OK (LComment "Saving a0-a7,t0-t6" :: save_a_regs @ - LAddi(reg_sp, reg_s0, !Archi.wordsize * (ofs + 1)) :: + LAddi(reg_sp, reg_s0, (Archi.wordsize ()) * (ofs + 1)) :: parameter_passing @ LCall "print" :: LComment "Restoring a0-a7,t0-t6" :: restore_caller_save arg_saved) @@ -364,7 +366,7 @@ let ltl_fun_of_linear_fun linprog let prologue = List.concat (List.map make_push (Set.to_list callee_saved_regs)) @ LMov (reg_fp, reg_sp) :: - make_sp_sub (numspilled * !Archi.wordsize) @ + make_sp_sub (numspilled * (Archi.wordsize ())) @ [LComment "end prologue"] in let epilogue = LLabel epilogue_label :: LMov(reg_sp, reg_fp) :: @@ -411,3 +413,11 @@ let ltl_prog_of_linear lp = ) lp in prog +let pass_ltl_gen linear = + match ltl_prog_of_linear linear with + | Error msg -> record_compile_result ~error:(Some msg) "LTL"; Error msg + | OK ltl -> + record_compile_result "LTL"; + dump !ltl_dump dump_ltl_prog ltl + (fun file () -> add_to_report "ltl" "LTL" (Code (file_contents file))); + OK ltl diff --git a/src/ltl_print.ml b/src/ltl_print.ml index bdabe2569a3d8f27638ba06ee2f40cf0380c7a14..57869ea001c1cd7872fbd8858e836306c3d0ca17 100644 --- a/src/ltl_print.ml +++ b/src/ltl_print.ml @@ -83,9 +83,9 @@ let dump_ltl_instr oc (i: ltl_instr) = Format.fprintf oc "%s <- %s %s" (print_reg rd) (print_unop u) (print_reg rs) | LStore(rt, i, rs, sz) -> - Format.fprintf oc "%s{%d}[%d] <- %s" (print_reg rt) sz i (print_reg rs) + Format.fprintf oc "%s%s[%d] <- %s" (print_reg rt) (string_of_mem_access_size sz) i (print_reg rs) | LLoad(rd, rt, i, sz) -> - Format.fprintf oc "%s <- %s{%d}[%d]" (print_reg rd) (print_reg rt) sz i + Format.fprintf oc "%s <- %s%s[%d]" (print_reg rd) (print_reg rt) (string_of_mem_access_size sz) i | LMov(rd, rs) -> Format.fprintf oc "%s <- %s" (print_reg rd) (print_reg rs) | LLabel l -> diff --git a/src/ltl_run.ml b/src/ltl_run.ml index 669033ddf153edbb3fe3bf39e3179a27170229fb..187fd87e33b8381c75061da070cbeb72246027fc 100644 --- a/src/ltl_run.ml +++ b/src/ltl_run.ml @@ -101,11 +101,11 @@ let exec_ltl_instr oc ip st : (int option) res = | LStore(rt, i, rs, sz) -> get_reg st rt $ fun vt -> get_reg st rs $ fun vs -> - Mem.write_bytes st.mem (vt + i) (split_bytes sz vs) >>= fun _ -> + Mem.write_bytes st.mem (vt + i) (split_bytes (size_of_mas sz) vs) >>= fun _ -> next ip | LLoad(rd, rt, i, sz) -> get_reg st rt $ fun vt -> - Mem.read_bytes_as_int st.mem (vt + i) sz >>= fun (v) -> + Mem.read_bytes_as_int st.mem (vt + i) (size_of_mas sz) >>= fun (v) -> Array.set st.regs rd v; next ip | LMov(rd, rs) -> @@ -201,9 +201,9 @@ let init_state memsize lp params = List.iteri (fun i p -> if i >= number_of_arguments_passed_in_registers then begin - let sp = Array.get regs reg_sp - !Archi.wordsize in + let sp = Array.get regs reg_sp - (Archi.wordsize ()) in Array.set regs reg_sp sp; - Mem.write_bytes mem sp (split_bytes !Archi.wordsize p) >>! + Mem.write_bytes mem sp (split_bytes (Archi.wordsize ()) p) >>! ignore end else begin @@ -211,7 +211,7 @@ let init_state memsize lp params = end ) params; let mem_next = ref (codesize + 8) in - Mem.write_bytes mem codesize (split_bytes !Archi.wordsize !mem_next) >>! + Mem.write_bytes mem codesize (split_bytes (Archi.wordsize ()) !mem_next) >>! fun _ -> Printf.eprintf "numlabels = %d\n" (Hashtbl.length labels); Printf.eprintf "labels = %s\n" (Hashtbl.keys labels |> List.of_enum |> String.concat ", "); diff --git a/src/main.ml b/src/main.ml index dcc6443e91d74bffbbb95463eecce131502f979b..abae9ca260acc9f72fcb64233144a76eac8b1b4e 100644 --- a/src/main.ml +++ b/src/main.ml @@ -35,12 +35,7 @@ open Archi open Report open Options open Lexer_generator - -open Cfg_loops - -let tokenize file = - Lexer_generator.tokenize_file file >>= fun tokens -> - OK (List.map (fun tok -> (tok, None)) tokens) +open Tokenize let speclist = [ @@ -51,7 +46,6 @@ let speclist = ("-e-run", Arg.Set e_run, "Run Elang program."); ("-cfg-dump", Arg.String (fun s -> cfg_dump := Some s), "Output CFG file."); ("-cfg-run", Arg.Set cfg_run, "Run CFG program."); - ("-cfg-run-after-loop", Arg.Set cfg_run_after_loop, "Run CFG program after loop optimization."); ("-cfg-run-after-cp", Arg.Set cfg_run_after_cp, "Run CFG program after constant propagation."); ("-cfg-run-after-dae", Arg.Set cfg_run_after_dae, "Run CFG program after dead assign elimination."); ("-cfg-run-after-ne", Arg.Set cfg_run_after_ne, "Run CFG program after nop elimination."); @@ -70,12 +64,15 @@ let speclist = ("-clever-regalloc", Arg.Unit (fun () -> naive_regalloc := false), "Use the graph coloring algorithm for register allocation."); ("-naive-regalloc", Arg.Unit (fun () -> naive_regalloc := true), "Use the naive algorithm for register allocation (all pseudo-registers go on the stack)."); + ("-no-cfg-constprop", Arg.Set no_cfg_constprop, "Disable CFG constprop"); + ("-no-cfg-dae", Arg.Set no_cfg_dae, "Disable CFG Dead Assign Elimination"); + ("-no-cfg-ne", Arg.Set no_cfg_ne, "Disable CFG Nop Elimination"); + ("-no-linear-dse", Arg.Set no_linear_dse, "Disable Linear Dead Store Elimination"); ("-rig-dump", Arg.String (fun s -> rig_dump := Some s), "Path to output the register interference graph"); ("-all-run", Arg.Unit (fun () -> e_run := true; cfg_run := true; - cfg_run_after_loop := true; cfg_run_after_cp := true; cfg_run_after_dae := true; cfg_run_after_ne := true; @@ -94,106 +91,11 @@ let speclist = ("-nostart", Arg.Set nostart, "Don't output _start code."); ("-nostats", Arg.Set nostats, "Don't output stats."); ("-nomul", Arg.Unit (fun _ -> has_mul := false), "Target architecture without mul instruction."); + ("-linux", Arg.Unit (fun _ -> target := Linux), "emit linux syscalls"); + ("-xv6", Arg.Unit (fun _ -> target := Xv6), "emit xv6 syscalls"); ("--", Arg.Rest (fun p -> params := int_of_string p::!params), "Run parameters.") ] - - -type run_result = { - step: string; - retval: int option; - output: string; - error: string option; - time: float; -} - -type compile_result = { - step: string; - error: string option; - data: Yojson.t -} - -type result = RunRes of run_result - | CompRes of compile_result - - -let results = ref [] - -let run step flag eval p = - if flag then begin - let starttime = Unix.gettimeofday () in - let res = match eval Format.str_formatter p !heapsize !params with - | exception e -> - Error (Printexc.to_string e) - | e -> e in - let timerun = Unix.gettimeofday () -. starttime in - begin match res with - | OK v -> - let output = Format.flush_str_formatter () in - results := !results @ [RunRes { step ; retval = v; output; error = None; time = timerun}]; - add_to_report step ("Run " ^ step) ( - Paragraph - ( - Printf.sprintf "With parameters : [%s]<br>\n" (String.concat"," (List.map string_of_int !params)) - ^ Printf.sprintf "Mem size : %d bytes<br>\n" !heapsize - ^ Printf.sprintf "Return value : %s<br>\n" (match v with | Some v -> string_of_int v | _ -> "none") - ^ Printf.sprintf "Output : <pre style=\"padding: 1em; background-color: #ccc;\">%s</pre>\n" output - ^ Printf.sprintf "Time : %f seconds<br>\n" timerun - ) - ) - | Error msg -> - let output = Format.flush_str_formatter () in - results := !results @ [RunRes { step ; retval = None; output; error = Some msg; time = timerun}]; - add_to_report step ("Run " ^ step) ( - Paragraph - ( - Printf.sprintf "With parameters : [%s]<br>\n" (String.concat"," (List.map string_of_int !params)) - ^ Printf.sprintf "Mem size : %d bytes<br>\n" !heapsize - ^ Printf.sprintf "Return value : none<br>\n" - ^ Printf.sprintf "Output : <pre style=\"padding: 1em; background-color: #ccc;\">%s</pre>\n" output - ^ Printf.sprintf "Error : <pre style=\"padding: 1em; background-color: #fcc;\">\n%s</pre>\n" msg - ^ Printf.sprintf "Time : %f seconds<br>\n" timerun - ) - ) - - end - end - -let record_compile_result ?error:(error=None) ?data:(data=[]) step = - let data = if not !Options.nostats then `List data else `Null in - results := !results @ [CompRes { step; error; data}] - - - -let process_output_to_list2 = fun command -> - let chan = Unix.open_process_in command in - let res = ref ([] : string list) in - let rec process_otl_aux () = - let e = input_line chan in - res := e::!res; - process_otl_aux() in - try process_otl_aux () - with End_of_file -> - let stat = Unix.close_process_in chan in (List.rev !res,stat) - -let cmd_to_list command = - let (l,_) = process_output_to_list2 command in l - -let file_contents file = - match - let ic = open_in file in - let rec aux s () = - try - let line = input_line ic in (* read line from in_channel and discard \n *) - aux (s ^ line ^ "\n") () (* close the input channel *) - with e -> (* some unexpected exception occurs *) - close_in_noerr ic; (* emergency closing *) - s in - aux "" () - with - | exception Sys_error _ -> failwith (Printf.sprintf "Could not open file %s\n" file) - | x -> x - let set_default r v suff = match !r with None -> r := Some (v ^ suff) @@ -201,13 +103,28 @@ let set_default r v suff = let compile_rv basename asmfile () = if not !Options.nostart then begin - let out, _ = - Format.sprintf - "%s -nostdlib -nostartfiles -T %s/link.ld -o \"%s.exe\" \"%s\" %s/lib%d.s %s/mul%d.S 2>&1" - !Archi.assembler Config.runtime_dir basename asmfile - Config.runtime_dir !Archi.nbits - Config.runtime_dir !Archi.nbits - |> process_output_to_list2 in + let obj_file_prog = Filename.temp_file ~temp_dir:"/tmp" "" ".o" in + let cmdas_prog = Format.sprintf "%s -I%s -o %s %s" + (Archi.assembler ()) + (Archi.runtime_lib_include_path ()) + obj_file_prog asmfile in + let obj_file_lib = Filename.temp_file ~temp_dir:"/tmp" "" ".o" in + let cmdas_lib = Format.sprintf "%s -I%s -o %s %s" + (Archi.assembler ()) + (Archi.runtime_lib_include_path ()) + obj_file_lib (Archi.runtime_lib_path ()) in + let cmdld = Format.sprintf "%s -T %s/link.ld %s %s -o %s.exe" + (Archi.linker ()) + Config.runtime_dir + obj_file_prog obj_file_lib + basename in + Printf.printf "AS: %s\n" cmdas_prog; + Printf.printf "AS: %s\n" cmdas_lib; + Printf.printf "LD: %s\n" cmdld; + let out_as_prog = cmd_to_list cmdas_prog in + let out_as_lib = cmd_to_list cmdas_lib in + let out_ld = cmd_to_list cmdld in + let out = out_as_prog @ out_as_lib @ out_ld in match out with [] -> None | _ -> Some (String.concat "\n" out) @@ -223,17 +140,12 @@ let exec_rv_prog ltl basename oc rvp heapsize params = f in let error = ref None in - dump (Some rvp) (fun oc p -> - match dump_riscv_prog oc p with - | OK _ -> () - | Error msg -> error := Some msg - ) ltl (fun file () -> - if !error = None - then error := compile_rv basename file ()); + dump (Some rvp) (dump_riscv_prog !Archi.target) ltl (fun file () -> + error := compile_rv basename file ()); match !error with | Some e -> Error ("RiscV generation error:\n" ^e) | None -> - let l = cmd_to_list (Format.sprintf "%s%d-static \"%s.exe\" %s" Config.qemu_path !Archi.nbits basename + let l = cmd_to_list (Format.sprintf "%s \"%s.exe\" %s" (Archi.qemu ()) basename (params |> List.map string_of_int |> String.concat " " )) in try let all_but_last = l |> List.rev |> List.tl |> List.rev in @@ -245,7 +157,7 @@ let exec_rv_prog ltl basename oc rvp heapsize params = let _ = Arg.parse speclist (fun s -> ()) "Usage"; - init_archi !archi (); + Archi.archi := !archi; match !input_file with | None -> failwith "No input file specified.\n" | Some input -> @@ -255,142 +167,54 @@ let _ = None -> failwith (Format.sprintf "File (%s) should end in .e" input) | Some basename -> - begin - params := List.rev !params; - set_default riscv_dump basename ".s"; - if not !no_dump then begin - set_default show_tokens basename ".lex"; - set_default ast_tree basename ".ast"; - set_default e_dump basename ".e.dump"; - set_default cfg_dump basename ".cfg"; - set_default rtl_dump basename ".rtl"; - set_default linear_dump basename ".linear"; - set_default rig_dump basename ".rig"; - set_default ltl_dump basename ".ltl"; - end; - - tokenize input >>* (fun msg -> - record_compile_result ~error:(Some msg) "Lexing"; - ) $ fun tokens -> - record_compile_result "Lexing"; - dump !show_tokens (fun oc tokens -> - List.iter (fun (tok,_) -> - Format.fprintf oc "%s\n" (string_of_symbol tok) - ) tokens) tokens (fun f () -> add_to_report "lexer" "Lexer" (Code (file_contents f))); - parse tokens () >>* (fun msg -> - record_compile_result ~error:(Some msg) "Parsing"; - ) $ fun (ast, tokens) -> - record_compile_result "Parsing"; - dump !ast_tree draw_ast_tree ast (call_dot "ast" "AST"); - if !ast_dump then Format.printf "%s\n" (string_of_ast ast) else (); - - match make_eprog_of_ast ast with - | Error msg -> record_compile_result ~error:(Some msg) "Elang" - | OK ep -> - dump !e_dump dump_e ep (fun file () -> - add_to_report "e" "E" (Code (file_contents file))); - run "Elang" !e_run eval_eprog ep; - - match cfg_prog_of_eprog ep with - | Error msg -> - record_compile_result ~error:(Some msg) "CFG"; - | OK cfg -> - record_compile_result ~data:([(`Assoc (List.map (fun (fname,Prog.Gfun cfgfun) -> (fname, `Int (Cfg.size_fun cfgfun.cfgfunbody))) cfg))]) "CFG"; - - dump !cfg_dump dump_cfg_prog cfg (call_dot "cfg" "CFG"); - run "CFG" !cfg_run eval_cfgprog cfg; - - let cfg = optimize_loop_cfg cfg in - record_compile_result ~data:([(`Assoc (List.map (fun (fname,Prog.Gfun cfgfun) -> (fname, `Int (Cfg.size_fun cfgfun.cfgfunbody))) cfg))]) "CFG loops"; - dump (!cfg_dump >*> fun s -> s ^ "0") dump_cfg_prog cfg - (call_dot "cfg-after-loop" "CFG after loop optim"); - run "CFG after loop optim" !cfg_run_after_loop eval_cfgprog cfg; - - - let cfg = constant_propagation cfg in - record_compile_result ~data:([(`Assoc (List.map (fun (fname,Prog.Gfun cfgfun) -> (fname, `Int (Cfg.size_fun cfgfun.cfgfunbody))) cfg))]) "Constprop"; - dump (!cfg_dump >*> fun s -> s ^ "1") dump_cfg_prog cfg - (call_dot "cfg-after-cstprop" "CFG after Constant Propagation"); - run "CFG after constant_propagation" !cfg_run_after_cp eval_cfgprog cfg; - - let cfg = dead_assign_elimination cfg in - record_compile_result ~data:([(`Assoc (List.map (fun (fname,Prog.Gfun cfgfun) -> (fname, `Int (Cfg.size_fun cfgfun.cfgfunbody))) cfg))]) "DeadAssign"; - dump (!cfg_dump >*> fun s -> s ^ "2") dump_cfg_prog cfg - (call_dot "cfg-after-dae" "CFG after DAE"); - run "CFG after dead_assign_elimination" !cfg_run_after_dae eval_cfgprog cfg; - - let cfg = nop_elimination cfg in - record_compile_result ~data:([(`Assoc (List.map (fun (fname,Prog.Gfun cfgfun) -> (fname, `Int (Cfg.size_fun cfgfun.cfgfunbody))) cfg))]) "NopElim"; - dump (!cfg_dump >*> fun s -> s ^ "3") dump_cfg_prog cfg - (call_dot "cfg-after-nop" "CFG after NOP elim"); - run "CFG after nop_elimination" !cfg_run_after_ne eval_cfgprog cfg; - - - let rtl = rtl_of_cfg cfg in - dump !rtl_dump dump_rtl_prog rtl - (fun file () -> add_to_report "rtl" "RTL" (Code (file_contents file))); - run "RTL" !rtl_run exec_rtl_prog rtl; - - let linear = linear_of_rtl rtl in - let lives = liveness_linear_prog linear in - dump !linear_dump (fun oc -> dump_linear_prog oc (Some lives)) linear - (fun file () -> add_to_report "linear" "Linear" (Code (file_contents file))); - run "Linear" !linear_run exec_linear_prog linear; - - let linear = dse_prog linear lives in - record_compile_result "DSE"; - dump (!linear_dump >*> fun s -> s ^ "1") - (fun oc -> dump_linear_prog oc (Some lives)) linear - (fun file () -> add_to_report "linear-after-dse" "Linear after DSE" - (Code (file_contents file))); - run "Linear after DSE" !linear_run_after_dse exec_linear_prog linear; - - match ltl_prog_of_linear linear with - | Error msg -> record_compile_result ~error:(Some msg) "LTL" - | OK ltl -> - dump !ltl_dump dump_ltl_prog ltl - (fun file () -> add_to_report "ltl" "LTL" (Code (file_contents file))); - run "LTL" !ltl_run (exec_ltl_prog) ltl; - (if !ltl_debug then debug_ltl_prog input ltl !heapsize !params); - - dump !riscv_dump (fun oc p -> - match dump_riscv_prog oc p with - | OK _ -> () - | Error msg -> record_compile_result ~error:(Some msg) "RISCV" - ) ltl (fun file () -> - add_to_report "riscv" "RISC-V" (Code (file_contents file)); - ignore (compile_rv basename file ())); - if not !Options.nostart then begin - run "Risc-V" !riscv_run (exec_rv_prog ltl basename) !riscv_dump - end; - + params := List.rev !params; + set_default riscv_dump basename ".s"; + if not !no_dump then begin + set_default show_tokens basename ".lex"; + set_default ast_tree basename ".ast"; + set_default e_dump basename ".e.dump"; + set_default cfg_dump basename ".cfg"; + set_default rtl_dump basename ".rtl"; + set_default linear_dump basename ".linear"; + set_default rig_dump basename ".rig"; + set_default ltl_dump basename ".ltl"; end; - let json_output_string = - let open Yojson in - let jstring_of_ostring o = - match o with - | None -> `Null - | Some s -> `String s - in - let j = `List (List.map (function - | RunRes { step; retval; output; error; time } -> - `Assoc [("runstep",`String step); - ("retval", match retval with Some r -> `Int r | None -> `Null); - ("output", `String output); - ("error", jstring_of_ostring error); - ("time", `Float time) - ] - | CompRes { step; error; data } -> - `Assoc [("compstep",`String step); - ("error", jstring_of_ostring error); - ("data", data) - ] - ) !results) in - (Yojson.pretty_to_string j) in - - + let compiler_res = + pass_tokenize input >>= fun tokens -> + pass_parse tokens >>= fun (ast, _) -> + pass_elang ast >>= fun ep -> + run "Elang" !e_run eval_eprog ep; + pass_cfg_gen ep >>= fun cfg -> + run "CFG" !cfg_run eval_cfgprog cfg; + pass_constant_propagation cfg >>= fun cfg -> + run "CFG after constant_propagation" !cfg_run_after_cp eval_cfgprog cfg; + pass_dead_assign_elimination cfg >>= fun cfg -> + run "CFG after dead_assign_elimination" !cfg_run_after_dae eval_cfgprog cfg; + pass_nop_elimination cfg >>= fun cfg -> + run "CFG after nop_elimination" !cfg_run_after_ne eval_cfgprog cfg; + pass_rtl_gen cfg >>= fun rtl -> + run "RTL" !rtl_run exec_rtl_prog rtl; + pass_linearize rtl >>= fun (linear, lives) -> + run "Linear" !linear_run exec_linear_prog linear; + pass_linear_dse linear lives >>= fun linear -> + run "Linear after DSE" !linear_run_after_dse exec_linear_prog linear; + pass_ltl_gen linear + in + begin + match compiler_res with + | Error msg -> () + | OK ltl -> + run "LTL" !ltl_run (exec_ltl_prog) ltl; + (if !ltl_debug then debug_ltl_prog input ltl !heapsize !params); + dump !riscv_dump (dump_riscv_prog !Archi.target) ltl (fun file () -> + add_to_report "riscv" "RISC-V" (Code (file_contents file)); + ignore (compile_rv basename file ())); + if not !Options.nostart then begin + run "Risc-V" !riscv_run (exec_rv_prog ltl basename) !riscv_dump + end + end; dump (Some !output_json) (fun oc p -> Format.fprintf oc "%s\n" p - ) json_output_string (fun _ () -> ()); + ) (json_output_string ()) (fun _ () -> ()); make_report input report () diff --git a/src/options.ml b/src/options.ml index b6bdd51360827630c4e5ca2f18a02186ac4bef2f..1c0772e2985065c16d018eacab623a88eb3439c5 100644 --- a/src/options.ml +++ b/src/options.ml @@ -30,6 +30,10 @@ let nostats = ref false let has_mul = ref true let no_dump = ref false let no_dot = ref false +let no_cfg_constprop = ref false +let no_cfg_dae = ref false +let no_cfg_ne = ref false +let no_linear_dse = ref false let alloc_order_st = ref true let naive_regalloc = ref true diff --git a/src/parser.ml b/src/parser.ml index 12a2a612370ccf93cad7214497156be05f1c90c2..8f0a0bae497d6afb406f5cdf744b04801ee44dcb 100644 --- a/src/parser.ml +++ b/src/parser.ml @@ -1,3 +1,16 @@ open Generated_parser +open Report +open Utils +open Options +open Ast let parse = parse_S + +let pass_parse tokens = + match parse tokens () with + | Error msg -> record_compile_result ~error:(Some msg) "Parsing"; Error msg + | OK (ast, tokens) -> + record_compile_result "Parsing"; + dump !ast_tree draw_ast_tree ast (call_dot "ast" "AST"); + if !ast_dump then Format.printf "%s\n" (string_of_ast ast) else (); + OK (ast, tokens) diff --git a/src/prog.ml b/src/prog.ml index 99b33608a8101c34a92cefb93a105ed21aa71e8a..ffe49805f8df8110f0786f8950f80bc6fd99bdfc 100644 --- a/src/prog.ml +++ b/src/prog.ml @@ -1,5 +1,37 @@ open Utils + +type mem_access_size = + | MAS1 + | MAS4 + | MAS8 + +let string_of_mem_access_size mas = + match mas with + | MAS1 -> "{1}" + | MAS4 -> "{4}" + | MAS8 -> "{8}" + +let mas_of_size n = + match n with + | 1 -> OK MAS1 + | 4 -> OK MAS4 + | 8 -> OK MAS8 + | _ -> Error (Printf.sprintf "Unknown memory access size for size = %d" n) + + +let size_of_mas mas = + match mas with + | MAS1 -> 1 + | MAS4 -> 4 + | MAS8 -> 8 + +let archi_mas () = + match !Archi.archi with + | A64 -> MAS8 + | A32 -> MAS4 + + type 'a gdef = Gfun of 'a type 'a prog = (string * 'a gdef) list diff --git a/src/report.ml b/src/report.ml index b60bb9c5a854c1b56c1ae7bba4906d8c5cb27730..94d927de878c060bb77cd7dfcb308de09e913dd9 100644 --- a/src/report.ml +++ b/src/report.ml @@ -1,3 +1,5 @@ +open Options +open Utils type html_node = | Img of string @@ -45,3 +47,88 @@ let call_dot report_sectid report_secttitle file () : unit = add_to_report report_sectid report_secttitle (Img (Filename.basename file^".svg")); ignore r end + +(* *) + + +type run_result = { + step: string; + retval: int option; + output: string; + error: string option; + time: float; +} + +type compile_result = { + step: string; + error: string option; + data: Yojson.t +} + +type result = RunRes of run_result + | CompRes of compile_result + + +let results : result list ref = ref [] + + +let record_compile_result ?error:(error=None) ?data:(data=[]) step = + let data = if not !Options.nostats then `List data else `Null in + results := !results @ [CompRes { step; error; data}] + + +let run step flag eval p = + if flag then begin + let starttime = Unix.gettimeofday () in + let res = match eval Format.str_formatter p !heapsize !params with + | exception e -> + Error (Printexc.to_string e) + | e -> e in + let timerun = Unix.gettimeofday () -. starttime in + let output = Format.flush_str_formatter () in + let rres = { step ; retval = None; output; error = None; time = timerun} in + let rres = + begin match res with + | OK v -> { rres with retval = v } + | Error msg -> { rres with error = Some msg } + end in + results := !results @ [RunRes rres]; + add_to_report step ("Run " ^ step) ( + Paragraph + ( + Printf.sprintf "With parameters : [%s]<br>\n" (String.concat"," (List.map string_of_int !params)) + ^ Printf.sprintf "Mem size : %d bytes<br>\n" !heapsize + ^ Printf.sprintf "Return value : %s<br>\n" (match rres.retval with | Some v -> string_of_int v | _ -> "none") + ^ Printf.sprintf "Output : <pre style=\"padding: 1em; background-color: #ccc;\">%s</pre>\n" output + ^ + (match rres.error with + | Some msg -> Printf.sprintf "Error : <pre style=\"padding: 1em; background-color: #fcc;\">\n%s</pre>\n" msg + | _ -> "") + ^ Printf.sprintf "Time : %f seconds<br>\n" timerun + ) + ) + end + + +let json_output_string () = + let open Yojson in + let jstring_of_ostring o = + match o with + | None -> `Null + | Some s -> `String s + in + let j = `List (List.map (function + | RunRes { step; retval; output; error; time } -> + `Assoc [("runstep",`String step); + ("retval", match retval with Some r -> `Int r | None -> `Null); + ("output", `String output); + ("error", jstring_of_ostring error); + ("time", `Float time) + ] + | CompRes { step; error; data } -> + `Assoc [("compstep",`String step); + ("error", jstring_of_ostring error); + ("data", data) + ] + ) !results) in + (Yojson.pretty_to_string j) diff --git a/src/riscv.ml b/src/riscv.ml index 9c6402b8330dd0d2e0a96cdcef04c198d312a764..c38276f44b0a8dea9de009f1daf0af7dccaebd35 100644 --- a/src/riscv.ml +++ b/src/riscv.ml @@ -7,6 +7,7 @@ open Ltl_print open Utils open Prog open Options +open Archi (* This file performs the translation from LTL programs to RISC-V assembly programs. The languages are basically the same, so the only thing to do here @@ -45,166 +46,126 @@ let print_binop (b: binop) = | Elang.Exor -> "xor" | Elang.Ediv -> "divu" | Elang.Esub -> "sub" - | _ -> assert false + | _ -> failwith "Unexpected binop" let print_unop (u: unop) = match u with | Elang.Eneg -> "neg" let instrsuffix_of_size sz = - match !Archi.archi, sz with - | _, 1 -> OK 'b' - | _, 4 -> OK 'w' - | A64, 8 -> OK 'd' - | _, _ -> - Error (Format.sprintf "Impossible write size (%d) in archi (%d)" - sz !Archi.nbits) + match sz with + | MAS1 -> 'b' + | MAS4 -> 'w' + | MAS8 -> 'd' let dump_riscv_instr oc (i: ltl_instr) = match i with | LAddi(rd, rs, i) -> - Format.fprintf oc "addi %s, %s, %d\n" (print_reg rd) (print_reg rs) i; - OK () + Format.fprintf oc "addi %s, %s, %d\n" (print_reg rd) (print_reg rs) i | LSubi(rd, rs, i) -> - Format.fprintf oc "addi %s, %s, %d\n" (print_reg rd) (print_reg rs) (-i); - OK () + Format.fprintf oc "addi %s, %s, %d\n" (print_reg rd) (print_reg rs) (-i) | LBinop(b, rd, rs1, rs2) -> begin match b with - | Elang.Eclt -> + | Elang.Eclt -> Format.fprintf oc "slt %s, %s, %s\n" - (print_reg rd) (print_reg rs1) (print_reg rs2); - OK () + (print_reg rd) (print_reg rs1) (print_reg rs2) | Elang.Ecgt -> Format.fprintf oc "slt %s, %s, %s\n" - (print_reg rd) (print_reg rs2) (print_reg rs1); - OK () + (print_reg rd) (print_reg rs2) (print_reg rs1) | Elang.Ecle -> - (* 'rd <- rs1 <= rs2' == 'rd <- rs2 < rs1; rd <- not rd' *) + (* 'rd <- rs1 <= rs2' == 'rd <- rs2 < rs1; rd <- seqz rd' *) Format.fprintf oc "slt %s, %s, %s\n" (print_reg rd) (print_reg rs2) (print_reg rs1); Format.fprintf oc "seqz %s, %s\n" - (print_reg rd) (print_reg rd); - OK () + (print_reg rd) (print_reg rd) | Elang.Ecge -> Format.fprintf oc "slt %s, %s, %s\n" (print_reg rd) (print_reg rs1) (print_reg rs2); Format.fprintf oc "seqz %s, %s\n" - (print_reg rd) (print_reg rd); - OK () + (print_reg rd) (print_reg rd) | Elang.Eceq -> Format.fprintf oc "sub %s, %s, %s\n" (print_reg rd) (print_reg rs1) (print_reg rs2); Format.fprintf oc "seqz %s, %s\n" - (print_reg rd) (print_reg rd); - OK () + (print_reg rd) (print_reg rd) | Elang.Ecne -> Format.fprintf oc "sub %s, %s, %s\n" (print_reg rd) (print_reg rs1) (print_reg rs2); Format.fprintf oc "snez %s, %s\n" - (print_reg rd) (print_reg rd); - OK () + (print_reg rd) (print_reg rd) | _ -> Format.fprintf oc "%s %s, %s, %s\n" - (print_binop b) (print_reg rd) (print_reg rs1) (print_reg rs2); - OK () + (print_binop b) (print_reg rd) (print_reg rs1) (print_reg rs2) end | LUnop(u, rd, rs) -> Format.fprintf oc "%s %s, %s\n" - (print_unop u) (print_reg rd) (print_reg rs); OK () + (print_unop u) (print_reg rd) (print_reg rs) | LStore(rt, i, rs, sz) -> - (instrsuffix_of_size sz) >>= fun sz -> - OK (Format.fprintf oc "s%c %s, %d(%s)\n" - sz (print_reg rs) i (print_reg rt)) + let sz = instrsuffix_of_size sz in + Format.fprintf oc "s%c %s, %d(%s)\n" + sz (print_reg rs) i (print_reg rt) | LLoad(rd, rt, i, sz) -> - (instrsuffix_of_size sz) >>= fun sz -> + let sz = (instrsuffix_of_size sz) in Format.fprintf oc "l%c %s, %d(%s)\n" - sz (print_reg rd) i (print_reg rt); OK () + sz (print_reg rd) i (print_reg rt) | LMov(rd, rs) -> - Format.fprintf oc "mv %s, %s\n" (print_reg rd) (print_reg rs); - OK () + Format.fprintf oc "mv %s, %s\n" (print_reg rd) (print_reg rs) | LLabel l -> - Format.fprintf oc "%s:\n" l; - OK () - | LJmp l -> Format.fprintf oc "j %s\n" l; - OK () - | LJmpr r -> Format.fprintf oc "jr %s\n" (print_reg r); - OK () - | LConst (rd, i) -> Format.fprintf oc "li %s, %d\n\n" (print_reg rd) i; - OK () - | LComment l -> Format.fprintf oc "# %s\n" l; - OK () + Format.fprintf oc "%s:\n" l + | LJmp l -> Format.fprintf oc "j %s\n" l + | LJmpr r -> Format.fprintf oc "jr %s\n" (print_reg r) + | LConst (rd, i) -> Format.fprintf oc "li %s, %d\n\n" (print_reg rd) i + | LComment l -> Format.fprintf oc "# %s\n" l | LBranch(cmp, rs1, rs2, s) -> Format.fprintf oc "%s %s, %s, %s\n" - (riscv_of_cmp cmp) (print_reg rs1) (print_reg rs2) s; - OK () + (riscv_of_cmp cmp) (print_reg rs1) (print_reg rs2) s | LCall fname -> - Format.fprintf oc "jal ra, %s\n" fname; - OK () - | LHalt -> Format.fprintf oc "halt\n"; - OK () + Format.fprintf oc "jal ra, %s\n" fname + | LHalt -> Format.fprintf oc "halt\n" let dump_riscv_fun oc (fname , lf) = Format.fprintf oc "%s:\n" fname; - list_iter_res (dump_riscv_instr oc) lf.ltlfunbody - -let riscv_load_args oc : unit res = - let nargs = [1;2;3;4;5;6;7;8] in - (* for each arg in [1..8]: - a0 <- arg - call load_int_arg - call atoi - sd a0, -8*arg(fp) - *) - let l1 = (nargs |> - List.map (fun i -> - [LConst(reg_a0, i); - LCall("load_int_arg"); - LBranch(Rceq, reg_a0, reg_zero, Printf.sprintf "riscv_load_arg_end"); - LCall("atoi"); - LStore(reg_fp, - !Archi.wordsize*i, - reg_a0, !Archi.wordsize); - ])) - @ - [[LLabel(Printf.sprintf "riscv_load_arg_end")]] - in - (* for each arg in [1..8] - ld a{arg-1}, -8*arg(fp) - *) - let l2 = nargs |> - List.map (fun i -> - [LLoad(starting_arg_register + i - 1, reg_fp, - - !Archi.wordsize*i, !Archi.wordsize)]) in - (l1 @ l2) |> List.concat |> list_iter_res (fun i -> dump_riscv_instr oc i) - - -let riscv_fun_load_arg oc () = - ("load_int_arg",{ - ltlfunargs = 0; - (* - - *( fp + a0 * wordsize + 8) - - t0 <- Archi.wordsize (in this example 8) - mul a0, a0, t0 - add t0, fp, a0 - ld a0, 8(t0) - jmpr ra - *) - ltlfunbody = [LConst(reg_t0, !Archi.wordsize); - LBinop(Emul, reg_ret, reg_ret, reg_t0); - LBinop(Eadd, reg_t0, reg_fp, reg_ret); - LLoad(reg_ret, reg_t0, !Archi.wordsize, !Archi.wordsize); - LJmpr reg_ra - ]; - ltlfuninfo = []; - ltlregalloc = [] - }) |> dump_riscv_fun oc + List.iter (dump_riscv_instr oc) lf.ltlfunbody + +let riscv_load_args target oc : unit = + (match target with + | Linux -> LLoad(reg_s1, reg_sp, 0, archi_mas ()) :: (* s1 <- argc *) + LAddi(reg_s2, reg_sp, (Archi.wordsize ())) :: [] + | Xv6 -> LMov(reg_s1, reg_a0) :: + LMov(reg_s2, reg_a1) :: []) @ + LConst(reg_s3, 1) :: + LSubi(reg_sp, reg_sp, 72) :: + LLabel "Lloop" :: + LBranch(Rceq, reg_s3, reg_s1, "Lendargs") :: + LMov(reg_a0, reg_t4) :: + LAddi(reg_s4, reg_s3, 0) :: + LConst(reg_t1, (Archi.wordsize ())) :: + LBinop(Emul, reg_s4, reg_s4, reg_t1) :: + LBinop(Eadd, reg_t3, reg_s4, reg_s2) :: + LLoad(reg_a0, reg_t3, 0, archi_mas ()) :: + LCall "atoi" :: + LBinop(Esub, reg_s4, reg_fp, reg_s4) :: + LStore(reg_s4, 0, reg_a0, archi_mas ()) :: + LAddi(reg_s3, reg_s3, 1) :: + LJmp "Lloop" :: + LLabel "Lendargs" :: + LLoad(reg_a0, reg_fp, -8, archi_mas ()) :: + LLoad(reg_a1, reg_fp, -16, archi_mas ()) :: + LLoad(reg_a2, reg_fp, -24, archi_mas ()) :: + LLoad(reg_a3, reg_fp, -32, archi_mas ()) :: + LLoad(reg_a4, reg_fp, -40, archi_mas ()) :: + LLoad(reg_a5, reg_fp, -48, archi_mas ()) :: + LLoad(reg_a6, reg_fp, -56, archi_mas ()) :: + LLoad(reg_a7, reg_fp, -64, archi_mas ()) :: + [] |> + List.iter (dump_riscv_instr oc) let rv_store () = - Format.sprintf "s%c" !Archi.instrsuffix + Format.sprintf "s%c" (Archi.instrsuffix ()) let rv_load () = - Format.sprintf "l%c" !Archi.instrsuffix + Format.sprintf "l%c" (Archi.instrsuffix ()) -let riscv_prelude oc = +let riscv_prelude target oc = + Format.fprintf oc ".include \"syscall_numbers.s\"\n"; Format.fprintf oc ".globl _start\n"; Format.fprintf oc "_start:\n"; Format.fprintf oc " lui gp, %%hi(_heap_start)\n"; @@ -212,22 +173,19 @@ let riscv_prelude oc = Format.fprintf oc " addi t0, gp, 8\n"; Format.fprintf oc " %s t0, 0(gp)\n" (rv_store ()); Format.fprintf oc " mv s0, sp\n"; - Format.fprintf oc " add sp, sp, -72\n"; - riscv_load_args oc >>= fun _ -> + riscv_load_args target oc ; Format.fprintf oc "jal ra, main\n"; Format.fprintf oc "mv s0, a0\n"; Format.fprintf oc "jal ra, println\n"; Format.fprintf oc "mv a0, s0\n"; Format.fprintf oc "jal ra, print_int\n"; Format.fprintf oc "jal ra, println\n"; - Format.fprintf oc "addi a7, zero, 93\n"; - Format.fprintf oc "ecall\n"; - OK () + Format.fprintf oc "addi a7, zero, SYSCALL_EXIT\n"; + Format.fprintf oc "ecall\n" -let dump_riscv_prog oc lp : unit res = - (if !nostart then OK () else riscv_prelude oc) >>= fun _ -> +let dump_riscv_prog target oc lp : unit = + (if !nostart then () else riscv_prelude target oc); Format.fprintf oc ".global main\n"; - list_iter_res (function + List.iter (function (fname, Gfun f) -> dump_riscv_fun oc (fname,f) - ) lp >>= fun _ -> - riscv_fun_load_arg oc () + ) lp diff --git a/src/rtl_gen.ml b/src/rtl_gen.ml index e9b62e058e82d8483fd940ed88e0f01944d63142..ce1eb8f84ef214052bb074b76658d460ac7045df 100644 --- a/src/rtl_gen.ml +++ b/src/rtl_gen.ml @@ -4,6 +4,9 @@ open Cfg open Rtl open Prog open Utils +open Report +open Rtl_print +open Options (* Une partie de la génération de RTL consiste à allouer les variables dans des pseudo-registres RTL. @@ -89,3 +92,9 @@ let rtl_of_gdef funname = function Gfun f -> Gfun (rtl_instrs_of_cfg_fun funname f) let rtl_of_cfg cp = List.map (fun (s, gd) -> (s, rtl_of_gdef s gd)) cp + +let pass_rtl_gen cfg = + let rtl = rtl_of_cfg cfg in + dump !rtl_dump dump_rtl_prog rtl + (fun file () -> add_to_report "rtl" "RTL" (Code (file_contents file))); + OK rtl diff --git a/src/test_lexer.ml b/src/test_lexer.ml index fa64acc93c566c2c6e2ff5af64b251d973dc4d8c..6e3adc92fd7602379603b4289325afde92c331f8 100644 --- a/src/test_lexer.ml +++ b/src/test_lexer.ml @@ -8,6 +8,10 @@ let () = let regexp_list = [ (keyword_regexp "while", fun s -> Some (SYM_WHILE)); (keyword_regexp "if", fun s -> Some (SYM_IF)); + (Cat(letter_regexp, + Star(identifier_material)), + fun s -> Some (SYM_IDENTIFIER s)); + ] in (* Décommentez la ligne suivante pour tester sur la vraie liste d'expressions régulières. *) @@ -29,4 +33,82 @@ let () = dfa_to_dot oc dfa alphabet; close_out oc; + let n = + { + nfa_states = [1; 2; 3; 4] ; + nfa_initial = [1] ; + nfa_final = [(3, fun s -> None); (4, fun s -> None)]; + nfa_step = fun q -> + match q with + | 1 -> [(Some (Set.singleton '0'), 2); (None, 3)] + | 2 -> [(Some (Set.singleton '1'), 2); (Some (Set.singleton '1'), 4)] + | 3 -> [(Some (Set.singleton '0'), 4); (None, 2)] + | 4 -> [(Some (Set.singleton '0'), 2)] + | _ -> [] + + } in + + let expect_set str s_got s_exp = + if Set.equal s_got s_exp + then Printf.printf "[OK] %s\n" str + else Printf.printf "[KO] %s : got %s, expected %s\n" str (string_of_int_set s_got) + (string_of_int_set s_exp) in + + let ec1 = epsilon_closure n 1 in + let ec2 = epsilon_closure n 2 in + let ec3 = epsilon_closure n 3 in + let ec4 = epsilon_closure n 4 in + + expect_set "epsilon_closure 1" ec1 (Set.of_list [1;2;3]); + expect_set "epsilon_closure 2" ec2 (Set.of_list [2]); + expect_set "epsilon_closure 3" ec3 (Set.of_list [2;3]); + expect_set "epsilon_closure 4" ec4 (Set.of_list [4]); + + expect_set "dfa_initial_state" (dfa_initial_state n) (Set.of_list [1;2;3]); + + let string_of_opt_tok ot = + match ot with + None -> "None" + | Some t -> Printf.sprintf "Some (%s)" (string_of_symbol t) + in + + let expect_token_option str to_got to_exp = + if to_got = to_exp + then Printf.printf "[OK] %s\n" str + else Printf.printf "[KO] %s : got %s, expected %s\n" str (string_of_opt_tok to_got) + (string_of_opt_tok to_exp) + in + + expect_token_option "min_priority 1" (min_priority [SYM_EOF; SYM_IDENTIFIER "bla"; SYM_WHILE]) (Some SYM_WHILE); + expect_token_option "min_priority 2" (min_priority [SYM_EOF; SYM_IDENTIFIER "bla"]) (Some (SYM_IDENTIFIER "bla")); + expect_token_option "min_priority 3" (min_priority [SYM_EOF; SYM_WHILE]) (Some SYM_WHILE); + + expect_token_option "min_priority 4" (min_priority []) None; + + let set_incl s1 s2 = + Set.for_all (fun s -> Set.exists (Set.equal s) s2) s1 + in + + let set_eq s1 s2 = set_incl s1 s2 && set_incl s2 s1 in + + let string_of_int_set_set s = + Set.map (fun s -> + Printf.sprintf "{%s}" (String.concat "," (Set.to_list (Set.map string_of_int s))) + ) s + |> Set.to_list + |> String.concat ", " + |> Printf.sprintf "{%s}" + in + + let expect_set_set str (set_got : int set set) (set_exp : int set set) = + if set_eq set_got set_exp + then Printf.printf "[OK] %s\n" str + else Printf.printf "[KO] %s : got %s, expected %s\n" str + (string_of_int_set_set set_got) + (string_of_int_set_set set_exp) + in + + let table = Hashtbl.create 10 in + build_dfa_table table n (dfa_initial_state n); + expect_set_set "dfa states" (Hashtbl.keys table |> Set.of_enum) (Set.of_list [Set.of_list [1;2;3]; Set.of_list [2;4]; Set.of_list [2]]) diff --git a/src/tokenize.ml b/src/tokenize.ml new file mode 100644 index 0000000000000000000000000000000000000000..8a1443915ca061f670dd996f081513bcd1264270 --- /dev/null +++ b/src/tokenize.ml @@ -0,0 +1,23 @@ +open Batteries +open Lexer_generator +open Report +open Utils +open Options +open Symbols + +let tokenize file = + Lexer_generator.tokenize_file file >>= fun tokens -> + OK (List.map (fun tok -> (tok, None)) tokens) + + +let pass_tokenize file = + tokenize file >>* (fun msg -> + record_compile_result ~error:(Some msg) "Lexing"; + Error msg + ) $ fun tokens -> + record_compile_result "Lexing"; + dump !show_tokens (fun oc tokens -> + List.iter (fun (tok,_) -> + Format.fprintf oc "%s\n" (string_of_symbol tok) + ) tokens) tokens (fun f () -> add_to_report "lexer" "Lexer" (Code (file_contents f))); + OK tokens diff --git a/src/utils.ml b/src/utils.ml index a954803ef76c3a4cda29afb42341e73d93a058df..aec74d5ff09c3737afc1d35d4617625c553e9873 100644 --- a/src/utils.ml +++ b/src/utils.ml @@ -113,7 +113,7 @@ let read_mem_bytes_as_int mem addr n = let read_mem_int mem addr = - read_mem_bytes_as_int mem addr !Archi.wordsize + read_mem_bytes_as_int mem addr (Archi.wordsize ()) let read_mem_char mem addr = read_mem_bytes mem addr 1 >>= fun bl -> @@ -318,3 +318,33 @@ let dump file (dumpf : _ -> 'a -> unit) (p: 'a) (additional_command: string -> u dumpf oc p; close (); if file <> "-" then additional_command file () end + + +let process_output_to_list2 = fun command -> + let chan = Unix.open_process_in command in + let res = ref ([] : string list) in + let rec process_otl_aux () = + let e = input_line chan in + res := e::!res; + process_otl_aux() in + try process_otl_aux () + with End_of_file -> + let stat = Unix.close_process_in chan in (List.rev !res,stat) + +let cmd_to_list command = + let (l,_) = process_output_to_list2 command in l + +let file_contents file = + match + let ic = open_in file in + let rec aux s () = + try + let line = input_line ic in (* read line from in_channel and discard \n *) + aux (s ^ line ^ "\n") () (* close the input channel *) + with e -> (* some unexpected exception occurs *) + close_in_noerr ic; (* emergency closing *) + s in + aux "" () + with + | exception Sys_error _ -> failwith (Printf.sprintf "Could not open file %s\n" file) + | x -> x diff --git a/tests/Makefile b/tests/Makefile index d6b84292ea9b87d1a73d77bdf767a9afb263d2b0..78c3657f7a434bd91dd0b8d0d4c4a55edfd59f09 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,14 +1,20 @@ # if make is launched with a DIR variable, pass it as the -f option to test.py # 'make DIR=basic/mul*.e' launches all the files starting with mul in the basic directory # otherwise, use basic/*.e as a default -FILES := $(if $(DIR),-f $(DIR),-f basic/*.e) +FILES := $(if $(DIR),$(DIR),basic/*.e) OPTS := $(if $(OPTS), $(OPTS),) .PHONY: all all: ../main.native - ./test.py $(FILES) $(OPTS) + ./test.py -f $(FILES) $(OPTS) + +expect: ../main.native + OCAMLRUNPARAM=b ./test.py --make-expect -f $(FILES) $(OPTS) --args 1 2 3 + OCAMLRUNPARAM=b ./test.py --make-expect -f $(FILES) $(OPTS) --args 14 12 3 8 12 + for f in $(FILES); do ../main.native -f $$f -show-tokens $$f.expect_lexer; done + clean: - find . -name '*.ltl' -or -name '*.cfg' -or -name '*.exe' -or -name '*.s' -or -name '*.rtl' -or -name '*.ast' -or -name '*.cfg0' -or -name '*.cfg1' -or -name '*.cfg2' -or -name '*.cfg3' -or -name '*.riscv' -or -name '*.dump' -or -name '*.linear1' -or -name '*.linear' -or -name '*.html' -or -name '*.svg' -or -name '*.html' -or -name '*.lex' -or -name "*.json" | xargs -I{} rm {} + find . -name '*.rig' -or -name '*.ltl' -or -name '*.cfg' -or -name '*.exe' -or -name '*.s' -or -name '*.rtl' -or -name '*.ast' -or -name '*.cfg0' -or -name '*.cfg1' -or -name '*.cfg2' -or -name '*.cfg3' -or -name '*.riscv' -or -name '*.dump' -or -name '*.linear1' -or -name '*.linear' -or -name '*.html' -or -name '*.svg' -or -name '*.html' -or -name '*.lex' -or -name "*.json" | xargs -I{} rm {} rm -rf __pycache__ diff --git a/tests/funcall/argswap.e.expect_lexer b/tests/funcall/argswap.e.expect_lexer index 89b98c324fdb2b227f987c44d6cd1bba0c75859d..2c8a87dc1d273f5d6156be905b62504276797c7b 100644 --- a/tests/funcall/argswap.e.expect_lexer +++ b/tests/funcall/argswap.e.expect_lexer @@ -5,12 +5,12 @@ SYM_COMMA SYM_IDENTIFIER(b) SYM_RPARENTHESIS SYM_LBRACE -SYM_PRINT +SYM_IDENTIFIER(print) SYM_LPARENTHESIS SYM_IDENTIFIER(a) SYM_RPARENTHESIS SYM_SEMICOLON -SYM_PRINT +SYM_IDENTIFIER(print) SYM_LPARENTHESIS SYM_IDENTIFIER(b) SYM_RPARENTHESIS @@ -30,12 +30,12 @@ SYM_COMMA SYM_IDENTIFIER(b) SYM_RPARENTHESIS SYM_LBRACE -SYM_PRINT +SYM_IDENTIFIER(print) SYM_LPARENTHESIS SYM_IDENTIFIER(a) SYM_RPARENTHESIS SYM_SEMICOLON -SYM_PRINT +SYM_IDENTIFIER(print) SYM_LPARENTHESIS SYM_IDENTIFIER(b) SYM_RPARENTHESIS diff --git a/tests/funcall/print_and_fun.e.expect_lexer b/tests/funcall/print_and_fun.e.expect_lexer index d8e49347bfd160352797416d6be13177edbc3ee4..834218f66d791aed054dec525bb4e0e33596260b 100644 --- a/tests/funcall/print_and_fun.e.expect_lexer +++ b/tests/funcall/print_and_fun.e.expect_lexer @@ -21,12 +21,12 @@ SYM_LPARENTHESIS SYM_INTEGER(8) SYM_RPARENTHESIS SYM_SEMICOLON -SYM_PRINT +SYM_IDENTIFIER(print) SYM_LPARENTHESIS SYM_IDENTIFIER(a) SYM_RPARENTHESIS SYM_SEMICOLON -SYM_PRINT +SYM_IDENTIFIER(print) SYM_LPARENTHESIS SYM_IDENTIFIER(b) SYM_RPARENTHESIS diff --git a/tests/globals/arrayptr.e b/tests/globals/arrayptr.e new file mode 100644 index 0000000000000000000000000000000000000000..e5d1b0d96515e4114a4edb031df15643097ca15e --- /dev/null +++ b/tests/globals/arrayptr.e @@ -0,0 +1,24 @@ +struct S { + int x; + int y; + int z; +}; + +struct S *p; + +struct S t[3]; + +int main(){ + (t[0]).x = 1; + (t[0]).y = 2; + (t[0]).z = 3; + (t[1]).x = 4; + (t[1]).y = 5; + (t[1]).z = 6; + (t[2]).x = 7; + (t[2]).y = 8; + (t[2]).z = 9; + p = &(t[2]); + + return (*p).y; +} diff --git a/tests/globals/arrayptr.e.expect_14_12_3_8_12 b/tests/globals/arrayptr.e.expect_14_12_3_8_12 new file mode 100644 index 0000000000000000000000000000000000000000..61b83a85dd0aeeb0ff59aaeb795875114625cdf7 --- /dev/null +++ b/tests/globals/arrayptr.e.expect_14_12_3_8_12 @@ -0,0 +1 @@ +{"output": "", "error": null, "retval": 8} \ No newline at end of file diff --git a/tests/globals/arrayptr.e.expect_1_2_3 b/tests/globals/arrayptr.e.expect_1_2_3 new file mode 100644 index 0000000000000000000000000000000000000000..61b83a85dd0aeeb0ff59aaeb795875114625cdf7 --- /dev/null +++ b/tests/globals/arrayptr.e.expect_1_2_3 @@ -0,0 +1 @@ +{"output": "", "error": null, "retval": 8} \ No newline at end of file diff --git a/tests/globals/arrayptr.e.expect_lexer b/tests/globals/arrayptr.e.expect_lexer new file mode 100644 index 0000000000000000000000000000000000000000..1c2e857c384ad3c3582f64a43a9a94110e617de6 --- /dev/null +++ b/tests/globals/arrayptr.e.expect_lexer @@ -0,0 +1,150 @@ +SYM_STRUCT +SYM_IDENTIFIER(S) +SYM_LBRACE +SYM_INT +SYM_IDENTIFIER(x) +SYM_SEMICOLON +SYM_INT +SYM_IDENTIFIER(y) +SYM_SEMICOLON +SYM_INT +SYM_IDENTIFIER(z) +SYM_SEMICOLON +SYM_RBRACE +SYM_SEMICOLON +SYM_STRUCT +SYM_IDENTIFIER(S) +SYM_ASTERISK +SYM_IDENTIFIER(p) +SYM_SEMICOLON +SYM_STRUCT +SYM_IDENTIFIER(S) +SYM_IDENTIFIER(t) +SYM_LBRACKET +SYM_INTEGER(3) +SYM_RBRACKET +SYM_SEMICOLON +SYM_INT +SYM_IDENTIFIER(main) +SYM_LPARENTHESIS +SYM_RPARENTHESIS +SYM_LBRACE +SYM_LPARENTHESIS +SYM_IDENTIFIER(t) +SYM_LBRACKET +SYM_INTEGER(0) +SYM_RBRACKET +SYM_RPARENTHESIS +SYM_POINT +SYM_IDENTIFIER(x) +SYM_ASSIGN +SYM_INTEGER(1) +SYM_SEMICOLON +SYM_LPARENTHESIS +SYM_IDENTIFIER(t) +SYM_LBRACKET +SYM_INTEGER(0) +SYM_RBRACKET +SYM_RPARENTHESIS +SYM_POINT +SYM_IDENTIFIER(y) +SYM_ASSIGN +SYM_INTEGER(2) +SYM_SEMICOLON +SYM_LPARENTHESIS +SYM_IDENTIFIER(t) +SYM_LBRACKET +SYM_INTEGER(0) +SYM_RBRACKET +SYM_RPARENTHESIS +SYM_POINT +SYM_IDENTIFIER(z) +SYM_ASSIGN +SYM_INTEGER(3) +SYM_SEMICOLON +SYM_LPARENTHESIS +SYM_IDENTIFIER(t) +SYM_LBRACKET +SYM_INTEGER(1) +SYM_RBRACKET +SYM_RPARENTHESIS +SYM_POINT +SYM_IDENTIFIER(x) +SYM_ASSIGN +SYM_INTEGER(4) +SYM_SEMICOLON +SYM_LPARENTHESIS +SYM_IDENTIFIER(t) +SYM_LBRACKET +SYM_INTEGER(1) +SYM_RBRACKET +SYM_RPARENTHESIS +SYM_POINT +SYM_IDENTIFIER(y) +SYM_ASSIGN +SYM_INTEGER(5) +SYM_SEMICOLON +SYM_LPARENTHESIS +SYM_IDENTIFIER(t) +SYM_LBRACKET +SYM_INTEGER(1) +SYM_RBRACKET +SYM_RPARENTHESIS +SYM_POINT +SYM_IDENTIFIER(z) +SYM_ASSIGN +SYM_INTEGER(6) +SYM_SEMICOLON +SYM_LPARENTHESIS +SYM_IDENTIFIER(t) +SYM_LBRACKET +SYM_INTEGER(2) +SYM_RBRACKET +SYM_RPARENTHESIS +SYM_POINT +SYM_IDENTIFIER(x) +SYM_ASSIGN +SYM_INTEGER(7) +SYM_SEMICOLON +SYM_LPARENTHESIS +SYM_IDENTIFIER(t) +SYM_LBRACKET +SYM_INTEGER(2) +SYM_RBRACKET +SYM_RPARENTHESIS +SYM_POINT +SYM_IDENTIFIER(y) +SYM_ASSIGN +SYM_INTEGER(8) +SYM_SEMICOLON +SYM_LPARENTHESIS +SYM_IDENTIFIER(t) +SYM_LBRACKET +SYM_INTEGER(2) +SYM_RBRACKET +SYM_RPARENTHESIS +SYM_POINT +SYM_IDENTIFIER(z) +SYM_ASSIGN +SYM_INTEGER(9) +SYM_SEMICOLON +SYM_IDENTIFIER(p) +SYM_ASSIGN +SYM_AMPERSAND +SYM_LPARENTHESIS +SYM_IDENTIFIER(t) +SYM_LBRACKET +SYM_INTEGER(2) +SYM_RBRACKET +SYM_RPARENTHESIS +SYM_SEMICOLON +SYM_RETURN +SYM_LPARENTHESIS +SYM_ASTERISK +SYM_IDENTIFIER(p) +SYM_RPARENTHESIS +SYM_POINT +SYM_IDENTIFIER(y) +SYM_SEMICOLON +SYM_RBRACE +SYM_EOF diff --git a/tests/globals/globtab2.e b/tests/globals/globtab2.e new file mode 100644 index 0000000000000000000000000000000000000000..c60b2cb694fca94bf9f89bcc26daebd145f92fd1 --- /dev/null +++ b/tests/globals/globtab2.e @@ -0,0 +1,43 @@ +int IMG[64]; +int NBCOL = 8; +int NBROW = 8; + +void draw(int color, int x, int y){ + int pos = (y * NBCOL + x); + if (pos < NBCOL * NBROW){ + *(IMG + pos) = color; + } +} + +int get(int x, int y){ + int pos = (y * NBCOL + x); + if (pos < NBCOL * NBROW){ + return *(IMG + pos); + } + return -1; +} + +void draw_world(){ + int i = 0; + int j = 0; + while (j < NBROW) { + i = 0; + while (i < NBCOL) { + if(get(i, j) != 0){ + print_char('#'); + } else { + print_char(' '); + } + i = i + 1; + } + print_char('\n'); + j = j + 1; + } +} + +int main(){ + draw(0xff0000, 1, 1); + print(get(1,1)); + draw_world(); + return 0; +} diff --git a/tests/globals/globtab2.e.expect_14_12_3_8_12 b/tests/globals/globtab2.e.expect_14_12_3_8_12 new file mode 100644 index 0000000000000000000000000000000000000000..b09bb6fba8ce6c934aecda5bb182415bced685ed --- /dev/null +++ b/tests/globals/globtab2.e.expect_14_12_3_8_12 @@ -0,0 +1 @@ +{"output": "16711680\n \n # \n \n \n \n \n \n \n", "error": null, "retval": 0} \ No newline at end of file diff --git a/tests/globals/globtab2.e.expect_1_2_3 b/tests/globals/globtab2.e.expect_1_2_3 new file mode 100644 index 0000000000000000000000000000000000000000..b09bb6fba8ce6c934aecda5bb182415bced685ed --- /dev/null +++ b/tests/globals/globtab2.e.expect_1_2_3 @@ -0,0 +1 @@ +{"output": "16711680\n \n # \n \n \n \n \n \n \n", "error": null, "retval": 0} \ No newline at end of file diff --git a/tests/globals/globtab2.e.expect_lexer b/tests/globals/globtab2.e.expect_lexer new file mode 100644 index 0000000000000000000000000000000000000000..c92540d9f191142eb924c6a1c74e1f898cb2098d --- /dev/null +++ b/tests/globals/globtab2.e.expect_lexer @@ -0,0 +1,217 @@ +SYM_INT +SYM_IDENTIFIER(IMG) +SYM_LBRACKET +SYM_INTEGER(64) +SYM_RBRACKET +SYM_SEMICOLON +SYM_INT +SYM_IDENTIFIER(NBCOL) +SYM_ASSIGN +SYM_INTEGER(8) +SYM_SEMICOLON +SYM_INT +SYM_IDENTIFIER(NBROW) +SYM_ASSIGN +SYM_INTEGER(8) +SYM_SEMICOLON +SYM_VOID +SYM_IDENTIFIER(draw) +SYM_LPARENTHESIS +SYM_INT +SYM_IDENTIFIER(color) +SYM_COMMA +SYM_INT +SYM_IDENTIFIER(x) +SYM_COMMA +SYM_INT +SYM_IDENTIFIER(y) +SYM_RPARENTHESIS +SYM_LBRACE +SYM_INT +SYM_IDENTIFIER(pos) +SYM_ASSIGN +SYM_LPARENTHESIS +SYM_IDENTIFIER(y) +SYM_ASTERISK +SYM_IDENTIFIER(NBCOL) +SYM_PLUS +SYM_IDENTIFIER(x) +SYM_RPARENTHESIS +SYM_SEMICOLON +SYM_IF +SYM_LPARENTHESIS +SYM_IDENTIFIER(pos) +SYM_LT +SYM_IDENTIFIER(NBCOL) +SYM_ASTERISK +SYM_IDENTIFIER(NBROW) +SYM_RPARENTHESIS +SYM_LBRACE +SYM_ASTERISK +SYM_LPARENTHESIS +SYM_IDENTIFIER(IMG) +SYM_PLUS +SYM_IDENTIFIER(pos) +SYM_RPARENTHESIS +SYM_ASSIGN +SYM_IDENTIFIER(color) +SYM_SEMICOLON +SYM_RBRACE +SYM_RBRACE +SYM_INT +SYM_IDENTIFIER(get) +SYM_LPARENTHESIS +SYM_INT +SYM_IDENTIFIER(x) +SYM_COMMA +SYM_INT +SYM_IDENTIFIER(y) +SYM_RPARENTHESIS +SYM_LBRACE +SYM_INT +SYM_IDENTIFIER(pos) +SYM_ASSIGN +SYM_LPARENTHESIS +SYM_IDENTIFIER(y) +SYM_ASTERISK +SYM_IDENTIFIER(NBCOL) +SYM_PLUS +SYM_IDENTIFIER(x) +SYM_RPARENTHESIS +SYM_SEMICOLON +SYM_IF +SYM_LPARENTHESIS +SYM_IDENTIFIER(pos) +SYM_LT +SYM_IDENTIFIER(NBCOL) +SYM_ASTERISK +SYM_IDENTIFIER(NBROW) +SYM_RPARENTHESIS +SYM_LBRACE +SYM_RETURN +SYM_ASTERISK +SYM_LPARENTHESIS +SYM_IDENTIFIER(IMG) +SYM_PLUS +SYM_IDENTIFIER(pos) +SYM_RPARENTHESIS +SYM_SEMICOLON +SYM_RBRACE +SYM_RETURN +SYM_MINUS +SYM_INTEGER(1) +SYM_SEMICOLON +SYM_RBRACE +SYM_VOID +SYM_IDENTIFIER(draw_world) +SYM_LPARENTHESIS +SYM_RPARENTHESIS +SYM_LBRACE +SYM_INT +SYM_IDENTIFIER(i) +SYM_ASSIGN +SYM_INTEGER(0) +SYM_SEMICOLON +SYM_INT +SYM_IDENTIFIER(j) +SYM_ASSIGN +SYM_INTEGER(0) +SYM_SEMICOLON +SYM_WHILE +SYM_LPARENTHESIS +SYM_IDENTIFIER(j) +SYM_LT +SYM_IDENTIFIER(NBROW) +SYM_RPARENTHESIS +SYM_LBRACE +SYM_IDENTIFIER(i) +SYM_ASSIGN +SYM_INTEGER(0) +SYM_SEMICOLON +SYM_WHILE +SYM_LPARENTHESIS +SYM_IDENTIFIER(i) +SYM_LT +SYM_IDENTIFIER(NBCOL) +SYM_RPARENTHESIS +SYM_LBRACE +SYM_IF +SYM_LPARENTHESIS +SYM_IDENTIFIER(get) +SYM_LPARENTHESIS +SYM_IDENTIFIER(i) +SYM_COMMA +SYM_IDENTIFIER(j) +SYM_RPARENTHESIS +SYM_NOTEQ +SYM_INTEGER(0) +SYM_RPARENTHESIS +SYM_LBRACE +SYM_IDENTIFIER(print_char) +SYM_LPARENTHESIS +SYM_CHARACTER(#) +SYM_RPARENTHESIS +SYM_SEMICOLON +SYM_RBRACE +SYM_ELSE +SYM_LBRACE +SYM_IDENTIFIER(print_char) +SYM_LPARENTHESIS +SYM_CHARACTER( ) +SYM_RPARENTHESIS +SYM_SEMICOLON +SYM_RBRACE +SYM_IDENTIFIER(i) +SYM_ASSIGN +SYM_IDENTIFIER(i) +SYM_PLUS +SYM_INTEGER(1) +SYM_SEMICOLON +SYM_RBRACE +SYM_IDENTIFIER(print_char) +SYM_LPARENTHESIS +SYM_CHARACTER( +) +SYM_RPARENTHESIS +SYM_SEMICOLON +SYM_IDENTIFIER(j) +SYM_ASSIGN +SYM_IDENTIFIER(j) +SYM_PLUS +SYM_INTEGER(1) +SYM_SEMICOLON +SYM_RBRACE +SYM_RBRACE +SYM_INT +SYM_IDENTIFIER(main) +SYM_LPARENTHESIS +SYM_RPARENTHESIS +SYM_LBRACE +SYM_IDENTIFIER(draw) +SYM_LPARENTHESIS +SYM_INTEGER(16711680) +SYM_COMMA +SYM_INTEGER(1) +SYM_COMMA +SYM_INTEGER(1) +SYM_RPARENTHESIS +SYM_SEMICOLON +SYM_IDENTIFIER(print) +SYM_LPARENTHESIS +SYM_IDENTIFIER(get) +SYM_LPARENTHESIS +SYM_INTEGER(1) +SYM_COMMA +SYM_INTEGER(1) +SYM_RPARENTHESIS +SYM_RPARENTHESIS +SYM_SEMICOLON +SYM_IDENTIFIER(draw_world) +SYM_LPARENTHESIS +SYM_RPARENTHESIS +SYM_SEMICOLON +SYM_RETURN +SYM_INTEGER(0) +SYM_SEMICOLON +SYM_RBRACE +SYM_EOF diff --git a/tests/invader/constants.s b/tests/invader/constants.S similarity index 100% rename from tests/invader/constants.s rename to tests/invader/constants.S diff --git a/tests/invader/crt.S b/tests/invader/crt.S new file mode 100644 index 0000000000000000000000000000000000000000..e5a63ba69a39f0939d4bce115d795025726fdad1 --- /dev/null +++ b/tests/invader/crt.S @@ -0,0 +1 @@ +.include "crtm.S" diff --git a/tests/invader/crt.s b/tests/invader/crt.s deleted file mode 100644 index dcdf1e15619b966fe805452be4aeaf56892fb577..0000000000000000000000000000000000000000 --- a/tests/invader/crt.s +++ /dev/null @@ -1 +0,0 @@ -.include "crtm.s" diff --git a/tests/invader/crtm.s b/tests/invader/crtm.S similarity index 96% rename from tests/invader/crtm.s rename to tests/invader/crtm.S index 158b3ce37b6d63155898f5f40916b043408ac200..e68162cf377d3687d3ce2c9d33bea465ac1c03b0 100644 --- a/tests/invader/crtm.s +++ b/tests/invader/crtm.S @@ -1,7 +1,7 @@ # See LICENSE for license details. -.include "macros.s" -.include "constants.s" +.include "macros.S" +.include "constants.S" # # start of trap handler diff --git a/tests/invader/include/font.h b/tests/invader/include/font.h index f65d48d250503448fea06af0668b1b630b80bb0e..58f066b5e4c9e162f153431ce2dc366e094dedfe 100644 --- a/tests/invader/include/font.h +++ b/tests/invader/include/font.h @@ -23,6 +23,6 @@ // Constant: font8x8_basic // Contains an 8x8 font map for unicode points U+0000 - U+007F (basic latin) -char font8x8_basic[256][8]; +extern char font8x8_basic[256][8]; #endif diff --git a/tests/invader/macros.s b/tests/invader/macros.S similarity index 100% rename from tests/invader/macros.s rename to tests/invader/macros.S diff --git a/tests/ptr/weird-ptr.e b/tests/ptr/weird-ptr.e new file mode 100644 index 0000000000000000000000000000000000000000..c6381bd7b5485fbbb7e542d43ed2fa850b532b23 --- /dev/null +++ b/tests/ptr/weird-ptr.e @@ -0,0 +1,11 @@ +int ignore(int * x){ + return 0; +} +int main(){ + int x = 0; + int y = 0; + ignore(&x); // force x on the stack + int* p = &y - 1; + *p = 3; + return x; +} diff --git a/tests/ptr/weird-ptr.e.expect_14_12_3_8_12 b/tests/ptr/weird-ptr.e.expect_14_12_3_8_12 new file mode 100644 index 0000000000000000000000000000000000000000..ff173ecdb8373e909da3d38e30940db4a55a4f2d --- /dev/null +++ b/tests/ptr/weird-ptr.e.expect_14_12_3_8_12 @@ -0,0 +1 @@ +{"output": "", "error": null, "retval": 3} \ No newline at end of file diff --git a/tests/ptr/weird-ptr.e.expect_1_2_3 b/tests/ptr/weird-ptr.e.expect_1_2_3 new file mode 100644 index 0000000000000000000000000000000000000000..ff173ecdb8373e909da3d38e30940db4a55a4f2d --- /dev/null +++ b/tests/ptr/weird-ptr.e.expect_1_2_3 @@ -0,0 +1 @@ +{"output": "", "error": null, "retval": 3} \ No newline at end of file diff --git a/tests/ptr/weird-ptr.e.expect_lexer b/tests/ptr/weird-ptr.e.expect_lexer new file mode 100644 index 0000000000000000000000000000000000000000..4862f4dd9c13bc662077b45b4963c847399f9d90 --- /dev/null +++ b/tests/ptr/weird-ptr.e.expect_lexer @@ -0,0 +1,52 @@ +SYM_INT +SYM_IDENTIFIER(ignore) +SYM_LPARENTHESIS +SYM_INT +SYM_ASTERISK +SYM_IDENTIFIER(x) +SYM_RPARENTHESIS +SYM_LBRACE +SYM_RETURN +SYM_INTEGER(0) +SYM_SEMICOLON +SYM_RBRACE +SYM_INT +SYM_IDENTIFIER(main) +SYM_LPARENTHESIS +SYM_RPARENTHESIS +SYM_LBRACE +SYM_INT +SYM_IDENTIFIER(x) +SYM_ASSIGN +SYM_INTEGER(0) +SYM_SEMICOLON +SYM_INT +SYM_IDENTIFIER(y) +SYM_ASSIGN +SYM_INTEGER(0) +SYM_SEMICOLON +SYM_IDENTIFIER(ignore) +SYM_LPARENTHESIS +SYM_AMPERSAND +SYM_IDENTIFIER(x) +SYM_RPARENTHESIS +SYM_SEMICOLON +SYM_INT +SYM_ASTERISK +SYM_IDENTIFIER(p) +SYM_ASSIGN +SYM_AMPERSAND +SYM_IDENTIFIER(y) +SYM_MINUS +SYM_INTEGER(1) +SYM_SEMICOLON +SYM_ASTERISK +SYM_IDENTIFIER(p) +SYM_ASSIGN +SYM_INTEGER(3) +SYM_SEMICOLON +SYM_RETURN +SYM_IDENTIFIER(x) +SYM_SEMICOLON +SYM_RBRACE +SYM_EOF diff --git a/tests/real_args/show_args.e b/tests/real_args/show_args.e deleted file mode 100644 index 31100a71533456cd92acc6064864a47f98630b3c..0000000000000000000000000000000000000000 --- a/tests/real_args/show_args.e +++ /dev/null @@ -1,15 +0,0 @@ -int main(int argc, char* argv[]){ - print_string("Program launched with "); - print_int(argc); - print_string(" arguments\n"); - int i = 0; - while(i < argc){ - print_string("argv["); - print_int(i); - print_string("] = "); - print_string(argv[i]); - print_string("\n"); - i = i + 1; - } - return argc; -} diff --git a/tests/strings/rot13.e b/tests/strings/rot13.e deleted file mode 100644 index 5b72b2ffbaffde899e3ffb556eeab1ecccd6faae..0000000000000000000000000000000000000000 --- a/tests/strings/rot13.e +++ /dev/null @@ -1,44 +0,0 @@ -int and(int a, int b){ - if(a != 0){ return b; } - return 0; -} - -int rot13c(char x){ - if('A' <= x){ - if (x <= 'Z'){ - return 'A' + (x - 'A' + 13) % 26; - } - } - if('a' <= x){ - if (x <= 'z'){ - return 'a' + (x - 'a' + 13) % 26; - } - } - return x; -} - -int rot13(char* c){ - int i = 0; - - while(c[i] != 0){ - c[i] = rot13c(c[i]); - i = i + 1; - } - return 0; -} -int main(int argc,char* argv[]){ - int a = atoi(argv[1]); - int b = atoi(argv[2]); - char c[10]; - c[0] = 'C'; - c[1] = 'o'; - c[2] = 'u'; - c[3] = 'c'; - c[4] = 'o'; - c[5] = 'u'; - c[6] = 0; - - rot13(c); - print_string(c); - return 0; -} diff --git a/tests/strings/string.e b/tests/strings/string.e deleted file mode 100644 index 05def8af5f92f07573e108f0b80b5235604ce28c..0000000000000000000000000000000000000000 --- a/tests/strings/string.e +++ /dev/null @@ -1,13 +0,0 @@ -int main(int argc,char* argv[]){ - char b[10]; - b[0] = 'H'; - b[1] = 'e'; - b[2] = 'l'; - b[3] = 'l'; - b[4] = 'o'; - b[5] = '!'; - b[6] = 0; - - print_string(b); - return 0; -} diff --git a/tests/strings/stringlit.e b/tests/strings/stringlit.e deleted file mode 100644 index 4e84976016821f26ea4685e7868a3d6eaa39ed40..0000000000000000000000000000000000000000 --- a/tests/strings/stringlit.e +++ /dev/null @@ -1,5 +0,0 @@ -int main(int argc,char* argv[]){ - char* c = "I am a string literal! Yay!\n"; - print_string(c); - return 0; -} diff --git a/tests/strings/stringlit2.e b/tests/strings/stringlit2.e deleted file mode 100644 index 643aeba161389002cad711fc6afc92c463af99c4..0000000000000000000000000000000000000000 --- a/tests/strings/stringlit2.e +++ /dev/null @@ -1,4 +0,0 @@ -int main(int argc,char* argv[]){ - print_string("I am a string literal! Yay!\n"); - return 0; -} diff --git a/tests/strings/stringlit3.e b/tests/strings/stringlit3.e deleted file mode 100644 index b0d76cf208a453d3b6e7418efe6170f910e87650..0000000000000000000000000000000000000000 --- a/tests/strings/stringlit3.e +++ /dev/null @@ -1,6 +0,0 @@ -int main(int argc,char* argv[]){ - char *c = "I am a string literal! Yay!\n"; - c[5] = 'A'; - print_string(c); - return 0; -} diff --git a/tests/strings/stringtab.e b/tests/strings/stringtab.e deleted file mode 100644 index 6afea99590336e3e2c71e31f72b47f4d4be7e07e..0000000000000000000000000000000000000000 --- a/tests/strings/stringtab.e +++ /dev/null @@ -1,10 +0,0 @@ -int main(int argc,char* argv[]){ - char* c = "Coucou\n"; - char* d = "Hello!\n"; - char* e[2]; - e[0] = c; - e[1] = d; - print_string(e[0]); - print_string(e[1]); - return 0; -} diff --git a/tests/structs/structtab.e b/tests/structs/structtab.e index 5fd4eac981a9242d3e4920220b1a1abdea43c16e..f28c3d354c19b88c5063634ef470148f7bf18852 100644 --- a/tests/structs/structtab.e +++ b/tests/structs/structtab.e @@ -2,7 +2,7 @@ struct S { int t[4]; }; -int main(int argc, char* argv[]){ +int main(){ struct S s; (s.t)[0] = 1; print_int((s.t)[0]); diff --git a/tests/structs/structtab.e.expect_14_12_3_8_12 b/tests/structs/structtab.e.expect_14_12_3_8_12 new file mode 100644 index 0000000000000000000000000000000000000000..8858d4cccf47c58c61f15b14873ea04ff1793568 --- /dev/null +++ b/tests/structs/structtab.e.expect_14_12_3_8_12 @@ -0,0 +1 @@ +{"output": "1", "error": null, "retval": 1} \ No newline at end of file diff --git a/tests/structs/structtab.e.expect_1_2_3 b/tests/structs/structtab.e.expect_1_2_3 new file mode 100644 index 0000000000000000000000000000000000000000..8858d4cccf47c58c61f15b14873ea04ff1793568 --- /dev/null +++ b/tests/structs/structtab.e.expect_1_2_3 @@ -0,0 +1 @@ +{"output": "1", "error": null, "retval": 1} \ No newline at end of file diff --git a/tests/structs/structtab.e.expect_lexer b/tests/structs/structtab.e.expect_lexer new file mode 100644 index 0000000000000000000000000000000000000000..1566d173fdc41a967b051fd8f02525da716c01e2 --- /dev/null +++ b/tests/structs/structtab.e.expect_lexer @@ -0,0 +1,55 @@ +SYM_STRUCT +SYM_IDENTIFIER(S) +SYM_LBRACE +SYM_INT +SYM_IDENTIFIER(t) +SYM_LBRACKET +SYM_INTEGER(4) +SYM_RBRACKET +SYM_SEMICOLON +SYM_RBRACE +SYM_SEMICOLON +SYM_INT +SYM_IDENTIFIER(main) +SYM_LPARENTHESIS +SYM_RPARENTHESIS +SYM_LBRACE +SYM_STRUCT +SYM_IDENTIFIER(S) +SYM_IDENTIFIER(s) +SYM_SEMICOLON +SYM_LPARENTHESIS +SYM_IDENTIFIER(s) +SYM_POINT +SYM_IDENTIFIER(t) +SYM_RPARENTHESIS +SYM_LBRACKET +SYM_INTEGER(0) +SYM_RBRACKET +SYM_ASSIGN +SYM_INTEGER(1) +SYM_SEMICOLON +SYM_IDENTIFIER(print_int) +SYM_LPARENTHESIS +SYM_LPARENTHESIS +SYM_IDENTIFIER(s) +SYM_POINT +SYM_IDENTIFIER(t) +SYM_RPARENTHESIS +SYM_LBRACKET +SYM_INTEGER(0) +SYM_RBRACKET +SYM_RPARENTHESIS +SYM_SEMICOLON +SYM_RETURN +SYM_LPARENTHESIS +SYM_IDENTIFIER(s) +SYM_POINT +SYM_IDENTIFIER(t) +SYM_RPARENTHESIS +SYM_LBRACKET +SYM_INTEGER(0) +SYM_RBRACKET +SYM_SEMICOLON +SYM_RBRACE +SYM_EOF diff --git a/tests/test.py b/tests/test.py index a0b25898501d4840b9155f3a9a3e9fe6b6cff7fb..fd9e2979ec1ec236c7ec16762d5ccd0c29452dfe 100755 --- a/tests/test.py +++ b/tests/test.py @@ -21,7 +21,6 @@ parser.add_argument("-p", "--passes", nargs='+', default=["e-run", "cfg-run", - "cfg-run-after-loop", "cfg-run-after-cp", "cfg-run-after-dae", "cfg-run-after-ne", @@ -144,13 +143,18 @@ class CommandExecutor(Thread): self.stderr = process['stderr'].decode('utf8') json_file_name = self.f + ".json" j = [] - with open(json_file_name, 'r') as jsonfile: - try: - j = json.load(jsonfile) - except: - j.append({'retval':-1, - 'output': display_verbatim(self.stdout), - 'error': display_verbatim(self.stderr)}) + try: + with open(json_file_name, 'r') as jsonfile: + try: + j = json.load(jsonfile) + except: + j.append({'retval':-1, + 'output': display_verbatim(self.stdout), + 'error': display_verbatim(self.stderr)}) + except: + j.append({'retval':-1, + 'output': display_verbatim(self.stdout), + 'error': "No file {} generated...".format(json_file_name)}) old_ret = None old_out = None old_err = None @@ -185,7 +189,7 @@ class CommandExecutor(Thread): self.lastcorrectstep = curcol self.s += make_td(["Ret = {}.<br>Output = <pre>'{}'</pre>{}<br>Time: {:.2f} seconds.<br>". format(r['retval'], r['output'], - "Error: "+r['error'] if r['error'] != None else "", + "Error: <pre>"+r['error']+"</pre>" if r['error'] != None else "", r['time']), "class=\"{}\"".format(cls)]) curcol+=1 diff --git a/tests/type_funcall/argswap-simple.e b/tests/type_funcall/argswap-simple.e new file mode 100644 index 0000000000000000000000000000000000000000..7af7b6a7fbca5a4ee0ce29b45204babd5711ae29 --- /dev/null +++ b/tests/type_funcall/argswap-simple.e @@ -0,0 +1,9 @@ +int g(int a,int b){ + return (b - a); +} +int f(int a, int b){ + return g(b, a); +} +int main(int x, int y){ + return f(x, y); +} diff --git a/tests/type_funcall/argswap-simple.e.expect_14_12_3_8_12 b/tests/type_funcall/argswap-simple.e.expect_14_12_3_8_12 new file mode 100644 index 0000000000000000000000000000000000000000..df1c5a5ba4e1647c7e3409ee9539a3583afa9bdf --- /dev/null +++ b/tests/type_funcall/argswap-simple.e.expect_14_12_3_8_12 @@ -0,0 +1 @@ +{"output": "", "error": null, "retval": 2} \ No newline at end of file diff --git a/tests/type_funcall/argswap-simple.e.expect_1_2_3 b/tests/type_funcall/argswap-simple.e.expect_1_2_3 new file mode 100644 index 0000000000000000000000000000000000000000..f8d80dd35ec68fe40bb34baeb5311e940a3ebfa9 --- /dev/null +++ b/tests/type_funcall/argswap-simple.e.expect_1_2_3 @@ -0,0 +1 @@ +{"output": "", "error": null, "retval": -1} \ No newline at end of file diff --git a/tests/type_funcall/argswap-simple.e.expect_lexer b/tests/type_funcall/argswap-simple.e.expect_lexer new file mode 100644 index 0000000000000000000000000000000000000000..034f6bd4babb9793eafad6000d158efd3ff168dc --- /dev/null +++ b/tests/type_funcall/argswap-simple.e.expect_lexer @@ -0,0 +1,57 @@ +SYM_INT +SYM_IDENTIFIER(g) +SYM_LPARENTHESIS +SYM_INT +SYM_IDENTIFIER(a) +SYM_COMMA +SYM_INT +SYM_IDENTIFIER(b) +SYM_RPARENTHESIS +SYM_LBRACE +SYM_RETURN +SYM_LPARENTHESIS +SYM_IDENTIFIER(b) +SYM_MINUS +SYM_IDENTIFIER(a) +SYM_RPARENTHESIS +SYM_SEMICOLON +SYM_RBRACE +SYM_INT +SYM_IDENTIFIER(f) +SYM_LPARENTHESIS +SYM_INT +SYM_IDENTIFIER(a) +SYM_COMMA +SYM_INT +SYM_IDENTIFIER(b) +SYM_RPARENTHESIS +SYM_LBRACE +SYM_RETURN +SYM_IDENTIFIER(g) +SYM_LPARENTHESIS +SYM_IDENTIFIER(b) +SYM_COMMA +SYM_IDENTIFIER(a) +SYM_RPARENTHESIS +SYM_SEMICOLON +SYM_RBRACE +SYM_INT +SYM_IDENTIFIER(main) +SYM_LPARENTHESIS +SYM_INT +SYM_IDENTIFIER(x) +SYM_COMMA +SYM_INT +SYM_IDENTIFIER(y) +SYM_RPARENTHESIS +SYM_LBRACE +SYM_RETURN +SYM_IDENTIFIER(f) +SYM_LPARENTHESIS +SYM_IDENTIFIER(x) +SYM_COMMA +SYM_IDENTIFIER(y) +SYM_RPARENTHESIS +SYM_SEMICOLON +SYM_RBRACE +SYM_EOF