MLIR DAG rewriter w/ SSA IR, dominance and CFG analysis passes
1

Configure Feed

Select the types of activity you want to include in your feed.

nemo / lib / parser.ml
3.3 kB 91 lines
1open Ir 2 3let read_lines path = 4 let ic = open_in path in 5 let lines = ref [] in 6 (try 7 while true do lines := input_line ic :: !lines done 8 with End_of_file -> close_in ic); 9 List.rev !lines 10 11let parse_func (lines : string list) : func = 12 let blocks = ref [] in 13 let current_id = ref 0 in 14 let current_insts = ref [] in 15 let finish_block () = 16 if !current_id <> 0 then 17 blocks := mk_block !current_id (List.rev !current_insts) :: !blocks; 18 current_id := 0; 19 current_insts := [] 20 in 21 let parse_instr s = 22 (* Tokenize: split on whitespace and standalone commas, but keep a 23 parenthesized group (e.g. "(10,2)") as a single token. This lets 24 "load 200, 100" and "phi 7 (10,2) (20,3)" both parse cleanly. *) 25 let tokens = ref [] in 26 let buf = Buffer.create 16 in 27 let depth = ref 0 in 28 let flush () = 29 if Buffer.length buf > 0 then begin 30 tokens := String.trim (Buffer.contents buf) :: !tokens; 31 Buffer.clear buf 32 end 33 in 34 String.iter (fun c -> 35 match c with 36 | '(' -> incr depth; Buffer.add_char buf c 37 | ')' -> decr depth; Buffer.add_char buf c 38 | (' ' | '\t' | '\n' | ',') when !depth = 0 -> 39 flush () 40 | _ -> Buffer.add_char buf c 41 ) s; 42 flush (); 43 let parts = List.rev !tokens in 44 match parts with 45 | "alloca" :: id :: [] -> Alloca (int_of_string id) 46 | "load" :: r :: p :: [] -> Load (int_of_string r, int_of_string p) 47 | "store" :: v :: p :: [] -> Store (int_of_string v, int_of_string p) 48 | "move" :: r :: v :: [] -> Move (int_of_string r, int_of_string v) 49 | "binop" :: r :: v1 :: v2 :: [] -> BinOp (int_of_string r, int_of_string v1, int_of_string v2) 50 | "phi" :: r :: ops -> 51 (* Each op is a parenthesized "(v,b)"; strip parens and split on ','. *) 52 let parse_op op = 53 (* Drop the surrounding parentheses, then split on ','. *) 54 let inner = String.sub op 1 (String.length op - 2) in 55 match String.split_on_char ',' inner with 56 | [v; b] -> (int_of_string (String.trim v), int_of_string (String.trim b)) 57 | _ -> failwith ("Bad phi operand: " ^ op) 58 in 59 Phi (int_of_string r, List.map parse_op ops) 60 | "ret" :: [] -> Ret None 61 | "ret" :: v :: [] -> Ret (Some (int_of_string v)) 62 | "br" :: t :: [] -> Br (int_of_string t) 63 | "condbr" :: c :: t1 :: t2 :: [] -> CondBr (int_of_string c, int_of_string t1, int_of_string t2) 64 | _ -> failwith ("Unknown instr: " ^ s) 65 in 66 List.iter (fun line -> 67 let trimmed = String.trim line in 68 if trimmed = "" then () 69 else if String.ends_with ~suffix:":" trimmed then 70 let label = String.sub trimmed 0 (String.length trimmed - 1) in 71 (* Accept either "1" or "block 1" style headers. *) 72 let id_str = 73 if String.starts_with ~prefix:"block " label 74 then String.sub label 6 (String.length label - 6) 75 else label 76 in 77 finish_block (); 78 current_id := int_of_string id_str 79 else 80 current_insts := parse_instr trimmed :: !current_insts 81 ) lines; 82 finish_block (); 83 let blocks = List.rev !blocks in 84 let entry = match blocks with 85 | [] -> 0 86 | b :: _ -> b.id 87 in 88 { blocks; entry } 89 90let parse_func_from_file path : func = 91 parse_func (read_lines path)