Skip to content

Commit 94d81f1

Browse files
committed
Add support for memcpy
1 parent af895aa commit 94d81f1

File tree

1 file changed

+37
-5
lines changed

1 file changed

+37
-5
lines changed

lib/ClangToAst.ml

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,9 @@ let translate_builtin_typ (t: Clang__Clang__ast.builtin_type) = match t with
9999
| ULongLong -> failwith "translate_builtin_typ: ulonglong"
100100
| UInt128 -> failwith "translate_builtin_typ: uint128"
101101

102+
| Int -> TInt Int32 (* TODO: Retrieve exact width *)
103+
102104
| Short
103-
| Int
104105
| Long
105106
| LongLong
106107
| Int128 -> failwith "translate_builtin_typ: signed int"
@@ -142,6 +143,15 @@ let rec translate_typ (typ: qual_type) = match typ.desc with
142143
(* Takes a Clangml expression [e], and retrieves the corresponding karamel Ast type *)
143144
let typ_of_expr (e: expr) : typ = Clang.Type.of_node e |> translate_typ
144145

146+
(* Check whether a given Clang expression is a memcpy callee *)
147+
let is_memcpy (e: expr) = match e.desc with
148+
| DeclRef { name; _ } ->
149+
let name = get_id_name name in
150+
name = "__builtin___memcpy_chk"
151+
| _ -> false
152+
153+
154+
145155
(* Translate expression [e], with expected type [t] *)
146156
let rec translate_expr' (env: env) (t: typ) (e: expr) : expr' = match e.desc with
147157
| IntegerLiteral (Int n) -> EConstant (Helpers.assert_tint t, string_of_int n)
@@ -168,7 +178,8 @@ let rec translate_expr' (env: env) (t: typ) (e: expr) : expr' = match e.desc wit
168178
let lhs_ty = typ_of_expr lhs in
169179
let lhs = translate_expr env (typ_of_expr lhs) lhs in
170180
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
181+
(* Rewrite the rhs into the compound expression, using the underlying operator *)
182+
let rhs = Ast.with_type lhs_ty (EApp (assign_to_bop kind, [lhs; rhs])) in
172183
begin match lhs.node with
173184
(* Special-case rewriting for buffer assignments *)
174185
| EBufRead (base, index) -> EBufWrite (base, index, rhs)
@@ -188,10 +199,29 @@ let rec translate_expr' (env: env) (t: typ) (e: expr) : expr' = match e.desc wit
188199

189200
| DeclRef {name; _} -> get_id_name name |> find_var env
190201

202+
| Call {callee; args} when is_memcpy callee ->
203+
(* Format.printf "Trying to translate memcpy %a@." Clang.Expr.pp e; *)
204+
begin match args with
205+
(* We are assuming here that this is __builtin___memcpy_chk.
206+
This function has a fourth argument, corresponding to the number of bytes
207+
remaining in dst. We omit it during the translation *)
208+
| [dst; src; len; _] ->
209+
let dst = translate_expr env (typ_of_expr dst) dst in
210+
let src = translate_expr env (typ_of_expr src) src in
211+
begin match len.desc with
212+
| BinaryOperator {lhs; kind = Mul; rhs = { desc = UnaryExpr {kind = SizeOf; _}; _}} ->
213+
let len = translate_expr env Helpers.usize lhs in
214+
EBufBlit (src, Helpers.zerou32, dst, Helpers.zerou32, len)
215+
| _ -> failwith "ill-formed memcpy"
216+
end
217+
| _ -> failwith "memcpy does not have the right number of arguments"
218+
end
219+
191220
| Call {callee; args} ->
192221
(* In C, a function type is a pointer. We need to strip it to retrieve
193222
the standard arrow abstraction *)
194223
let fun_typ = Helpers.assert_tbuf (typ_of_expr callee) in
224+
(* Format.printf "Trying to translate function call %a@." Clang.Expr.pp callee; *)
195225
let callee = translate_expr env fun_typ callee in
196226
let args = List.map (fun x -> translate_expr env (typ_of_expr x) x) args in
197227
EApp (callee, args)
@@ -210,9 +240,10 @@ let rec translate_expr' (env: env) (t: typ) (e: expr) : expr' = match e.desc wit
210240

211241
| ConditionalOperator _ -> failwith "translate_expr: conditional operator"
212242
| Paren _ -> failwith "translate_expr: paren"
213-
| SizeOfPack _ -> failwith "translate_expr: size_of"
214243

215-
| _ -> failwith "translate_expr: unsupported expression"
244+
| _ ->
245+
Format.printf "Trying to translate expression %a@." Clang.Expr.pp e;
246+
failwith "translate_expr: unsupported expression"
216247

217248
and translate_expr (env: env) (t: typ) (e: expr) : Ast.expr =
218249
Ast.with_type t (translate_expr' env t e)
@@ -254,7 +285,8 @@ let rec translate_stmt' (env: env) (t: typ) (s: stmt_desc) : expr' = match s wit
254285
(* The do statements first executes the body before behaving as a while loop.
255286
We thus translate it as a sequence of the body and the corresponding while loop *)
256287
let body = translate_stmt env t body.desc in
257-
let cond = translate_expr env TBool cond in
288+
(* TODO: Likely need to translate int conditions to boolean expressions *)
289+
let cond = translate_expr env (typ_of_expr cond) cond in
258290
ELet (
259291
Helpers.sequence_binding (),
260292
body,

0 commit comments

Comments
 (0)