@@ -14,10 +14,11 @@ let empty_env = {vars = []}
1414
1515let add_var env var = {vars = var :: env .vars }
1616
17- (* TODO: Handle fully qualified names/namespaces/different files *)
17+ (* TODO: Handle fully qualified names/namespaces/different files. *)
1818let find_var env var =
1919 try EBound (KList. index (fun x -> x = var) env.vars) with
2020 (* This variable is not a local var *)
21+ (* TODO: More robust check, likely need env for top-level decls * )
2122 | Not_found -> EQualified ([] , var)
2223
2324let get_id_name (dname : declaration_name ) = match dname with
@@ -30,16 +31,61 @@ let get_id_name (dname: declaration_name) = match dname with
3031 | LiteralOperatorName _ -> failwith " literal operator name"
3132 | UsingDirectiveName -> failwith " using directive"
3233
34+ let is_assign_op (kind : Clang__Clang__ast.binary_operator_kind ) = match kind with
35+ | Assign | AddAssign | MulAssign | DivAssign | RemAssign
36+ | SubAssign | ShlAssign | ShrAssign | AndAssign
37+ | XorAssign | OrAssign -> true
38+ | _ -> false
39+
40+ let assign_to_bop (kind : Clang__Clang__ast.binary_operator_kind ) : Ast.expr =
41+ let op = match kind with
42+ (* TODO: Might need to disambiguate for pointer arithmetic * )
43+ | AddAssign -> K. Add
44+ | MulAssign -> Mult
45+ | DivAssign -> Div
46+ | RemAssign -> Mod
47+ | SubAssign -> Sub
48+ | ShlAssign -> BShiftL
49+ | ShrAssign -> BShiftR
50+ | AndAssign -> BAnd
51+ (* TODO: Disambiguate *)
52+ | XorAssign -> BXor
53+ | OrAssign -> BOr
54+ | _ -> failwith " not an assign op"
55+ in
56+ (* TODO: Infer width and type from types of operands *)
57+ Ast. with_type Helpers. uint32 (EOp (op, UInt32 ))
58+
3359let translate_binop (kind : Clang__Clang__ast.binary_operator_kind ) : K.op = match kind with
60+ | PtrMemD | PtrMemI -> failwith " translate_binop: ptr mem"
61+ | Mul | Div | Rem -> failwith " translate_binop: arith expr"
62+
63+ (* TODO: Might need to disambiguate for pointer arithmetic *)
3464 | Add -> Add
65+ | Sub -> Sub
66+
67+ | Shl -> BShiftL
68+ | Shr -> BShiftR
69+
70+ | Cmp | LT | GT | LE | GE | EQ | NE -> failwith " translate_binop: boolcomp"
71+
72+ | And -> BAnd
3573 (* TODO: How to distinguish between Xor and BXor? Likely need typing info from operands *)
3674 | Xor -> BXor
3775 | Or -> BOr
38- | Shl -> BShiftL
39- | Shr -> BShiftR
40- | _ -> failwith " translate_binop"
76+
77+ | LAnd | LOr -> failwith " translate_binop: logical ops"
78+
79+ | Assign | AddAssign | MulAssign | DivAssign | RemAssign
80+ | SubAssign | ShlAssign | ShrAssign | AndAssign
81+ | XorAssign | OrAssign ->
82+ failwith " Assign operators should have been previously rewritten"
83+
84+ | Comma -> failwith " translate_binop: comma"
85+ | InvalidBinaryOperator -> failwith " translate_binop: invalid binop"
4186
4287let translate_typ_name = function
88+ | "size_t" -> Helpers. usize
4389 | "uint32_t" -> Helpers. uint32
4490 | s ->
4591 Printf. printf " type name %s is unsupported\n " s;
@@ -48,6 +94,17 @@ let translate_typ_name = function
4894let translate_builtin_typ (t : Clang__Clang__ast.builtin_type ) = match t with
4995 | Void -> TUnit
5096 | UInt -> TInt UInt32 (* TODO: How to retrieve exact width? *)
97+ | UShort -> failwith " translate_builtin_typ: ushort"
98+ | ULong -> TInt UInt32
99+ | ULongLong -> failwith " translate_builtin_typ: ulonglong"
100+ | UInt128 -> failwith " translate_builtin_typ: uint128"
101+
102+ | Short
103+ | Int
104+ | Long
105+ | LongLong
106+ | Int128 -> failwith " translate_builtin_typ: signed int"
107+
51108 | Pointer -> failwith " translate_builtin_typ: pointer"
52109 | _ -> failwith " translate_builtin_typ: unsupported builtin type"
53110
@@ -107,6 +164,17 @@ let rec translate_expr' (env: env) (t: typ) (e: expr) : expr' = match e.desc wit
107164 | _ -> EAssign (lhs, rhs)
108165 end
109166
167+ | BinaryOperator {lhs; kind; rhs} when is_assign_op kind ->
168+ let lhs_ty = typ_of_expr lhs in
169+ let lhs = translate_expr env (typ_of_expr lhs) lhs in
170+ let rhs = translate_expr env (typ_of_expr rhs) rhs in
171+ let rhs = Ast. with_type TUnit (EAssign (lhs, Ast. with_type lhs_ty (EApp (assign_to_bop kind, [lhs; rhs])))) in
172+ begin match lhs.node with
173+ (* Special-case rewriting for buffer assignments *)
174+ | EBufRead (base , index ) -> EBufWrite (base, index, rhs)
175+ | _ -> EAssign (lhs, rhs)
176+ end
177+
110178 | BinaryOperator {lhs; kind; rhs} ->
111179 let lhs_ty = typ_of_expr lhs in
112180 let lhs = translate_expr env lhs_ty lhs in
@@ -128,7 +196,11 @@ let rec translate_expr' (env: env) (t: typ) (e: expr) : expr' = match e.desc wit
128196 let args = List. map (fun x -> translate_expr env (typ_of_expr x) x) args in
129197 EApp (callee, args)
130198
131- | Cast _ -> failwith " translate_expr: cast"
199+ | Cast {qual_type; operand; _} ->
200+ (* Format.printf "Cast %a@." Clang.Expr.pp e; *)
201+ let typ = translate_typ qual_type in
202+ let e = translate_expr env (typ_of_expr operand) operand in
203+ ECast (e, typ)
132204
133205 | ArraySubscript {base; index} ->
134206 let base = translate_expr env (TBuf (t, false )) base in
@@ -137,6 +209,8 @@ let rec translate_expr' (env: env) (t: typ) (e: expr) : expr' = match e.desc wit
137209 EBufRead (base, index)
138210
139211 | ConditionalOperator _ -> failwith " translate_expr: conditional operator"
212+ | Paren _ -> failwith " translate_expr: paren"
213+ | SizeOfPack _ -> failwith " translate_expr: size_of"
140214
141215 | _ -> failwith " translate_expr: unsupported expression"
142216
@@ -151,6 +225,8 @@ let translate_vardecl (env: env) (vdecl: var_decl_desc) : env * binder * Ast.exp
151225 | Some e -> add_var env name, Helpers. fresh_binder name typ, translate_expr env typ e
152226
153227let rec translate_stmt ' (env : env ) (t : typ ) (s : stmt_desc ) : expr' = match s with
228+ | Null -> failwith " translate_stmt: null"
229+
154230 | Compound l -> begin match l with
155231 | [] -> EUnit
156232 | hd :: tl -> match hd.desc with
@@ -164,9 +240,42 @@ let rec translate_stmt' (env: env) (t: typ) (s: stmt_desc) : expr' = match s wit
164240 translate_stmt env TUnit stmt,
165241 translate_stmt (add_var env " _" ) t (Compound tl))
166242 end
243+
244+ | For _ -> failwith " translate_stmt: for"
245+ | ForRange _ -> failwith " translate_stmt: for range"
246+ | If _ -> failwith " translate_stmt: if"
247+
248+ | Switch _ -> failwith " translate_stmt: switch"
249+ | Case _ -> failwith " translate_stmt: case"
250+ | Default _ -> failwith " translate_stmt: default"
251+
252+ | While _ -> failwith " translate_stmt: while"
253+ | Do { body; cond } ->
254+ (* The do statements first executes the body before behaving as a while loop.
255+ We thus translate it as a sequence of the body and the corresponding while loop *)
256+ let body = translate_stmt env t body.desc in
257+ let cond = translate_expr env TBool cond in
258+ ELet (
259+ Helpers. sequence_binding () ,
260+ body,
261+ Ast. with_type TUnit (EWhile (cond, body))
262+ )
263+
264+ | Label _ -> failwith " translate_stmt: label"
265+ | Goto _ -> failwith " translate_stmt: goto"
266+ | IndirectGoto _ -> failwith " translate_stmt: indirect goto"
267+
268+ | Continue -> failwith " translate_stmt: continue"
269+ | Break -> failwith " translate_stmt: break"
270+ | Asm _ -> failwith " translate_stmt: asm"
271+ | Return _ -> failwith " translate_stmt: return"
272+
167273 | Decl _ -> failwith " translate_stmt: decl"
168274 | Expr e -> translate_expr' env t e
169- | _ -> failwith " translate_stmt"
275+
276+ | Try _ -> failwith " translate_stmt: try"
277+ | AttributedStmt _ -> failwith " translate_stmt: AttributedStmt"
278+ | UnknownStmt _ -> failwith " translate_stmt: UnknownStmt"
170279
171280and translate_stmt (env : env ) (t : typ ) (s : stmt_desc ) : Ast.expr =
172281 Ast. with_type t (translate_stmt' env t s)
@@ -199,18 +308,29 @@ let translate_fundecl (fdecl: function_decl) =
199308 (* KPrint.bprintf "Resulting decl %a\n" PrintAst.pdecl decl; *)
200309 decl
201310
202-
311+ (* TODO: Builtins might not be needed with a cleaner support for multiple files *)
203312let builtins = [
204313 (* Functions from inttypes.h *)
205- " imaxabs" ; " imaxdiv" ; " strtoimax" ; " strtoumax" ; " wcstoimax" ; " wcstoumax"
314+ " imaxabs" ; " imaxdiv" ; " strtoimax" ; " strtoumax" ; " wcstoimax" ; " wcstoumax" ;
315+ (* From string.h *)
316+ " __sputc" ; " _OSSwapInt16" ; " _OSSwapInt32" ; " _OSSwapInt64" ;
317+ (* Krml functions. TODO: Should be handled as multifile *)
318+ " krml_time" ;
206319]
207320
321+ (* Returning an option is only a hack to make progress.
322+ TODO: Proper handling of decls *)
208323let translate_decl (decl : decl ) = match decl.desc with
209324 | Function fdecl ->
210325 let name = get_id_name fdecl.name in
211- Printf. printf " Translating function %s\n " name;
212326 (* TODO: How to handle libc? *)
213- if List. mem name builtins then None else Some (translate_fundecl fdecl)
327+ let loc = Clang.Ast. location_of_node decl |> Clang.Ast. concrete_of_source_location File in
328+ let file_loc = loc.filename in
329+ (* TODO: Support multiple files *)
330+ if file_loc = " test.c" then (
331+ Printf. printf " Translating function %s\n " name;
332+ Some (translate_fundecl fdecl)
333+ ) else None
214334 | _ -> None
215335
216336let read_file () =
0 commit comments