From 0caac1aa938604905fac0f59a7d33dba3cc473ec Mon Sep 17 00:00:00 2001 From: Sam Blackshear Date: Mon, 24 Apr 2017 10:21:42 -0700 Subject: [PATCH] [hil] HIL expressions Summary: Expression language for new high-level IR. Reviewed By: jberdine Differential Revision: D4899313 fbshipit-source-id: 2aca792 --- infer/src/IR/HilExp.ml | 93 +++++++++++++++++++++++++++++++++++++++++ infer/src/IR/HilExp.mli | 41 ++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 infer/src/IR/HilExp.ml create mode 100644 infer/src/IR/HilExp.mli diff --git a/infer/src/IR/HilExp.ml b/infer/src/IR/HilExp.ml new file mode 100644 index 000000000..e06200461 --- /dev/null +++ b/infer/src/IR/HilExp.ml @@ -0,0 +1,93 @@ +(* + * Copyright (c) 2017 - present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + *) + +open! IStd + +module F = Format +module L = Logging + +type t = + | AccessPath of AccessPath.Raw.t + | UnaryOperator of Unop.t * t * Typ.t option + | BinaryOperator of Binop.t * t * t + | Exception of t + | Closure of Typ.Procname.t * (AccessPath.base * t) list + | Constant of Const.t + | Cast of Typ.t * t + | Sizeof of Typ.t * t option +[@@deriving compare] + +let rec pp fmt = function + | AccessPath access_path -> + AccessPath.Raw.pp fmt access_path + | UnaryOperator (op, e, _) -> + F.fprintf fmt "%s%a" (Unop.str op) pp e + | BinaryOperator(op, e1, e2) -> + F.fprintf fmt "%a %s %a" pp e1 (Binop.str Pp.text op) pp e2 + | Exception e -> + F.fprintf fmt "exception %a" pp e + | Closure (pname, _) -> + F.fprintf fmt "closure(%a)" Typ.Procname.pp pname + | Constant c -> + (Const.pp Pp.text) fmt c + | Cast (typ, e) -> + F.fprintf fmt "(%a) %a" (Typ.pp_full Pp.text) typ pp e + | Sizeof (typ, length) -> + let pp_length fmt = Option.iter ~f:(F.fprintf fmt "[%a]" pp) in + F.fprintf fmt "sizeof(%a%a)" (Typ.pp_full Pp.text) typ pp_length length + +let get_access_paths exp0 = + let rec get_access_paths_ exp acc = + match exp with + | AccessPath ap -> + ap :: acc + | Cast (_, e) | UnaryOperator (_, e, _) | Exception e | Sizeof (_, Some e) -> + get_access_paths_ e acc + | BinaryOperator (_, e1, e2) -> + get_access_paths_ e1 acc + |> get_access_paths_ e2 + | Closure _ | Constant _ | Sizeof _ -> + acc in + get_access_paths_ exp0 [] + +(* convert an SIL expression into an HIL expression. the [lookup_id] function should map an SSA + temporary variable to the access path it represents. evaluating the HIL expression should + produce the same result as evaluating the SIL expression and replacing the temporary variables + using [lookup_id] *) +let rec of_sil ~lookup_id (exp : Exp.t) typ = match exp with + | Var id -> + let ap = match lookup_id (Var.of_id id) with + | Some access_path -> access_path + | None -> AccessPath.of_id id typ in + AccessPath ap + | UnOp (op, e, typ_opt) -> + UnaryOperator (op, of_sil ~lookup_id e typ, typ_opt) + | BinOp (op, e0, e1) -> + BinaryOperator (op, of_sil ~lookup_id e0 typ, of_sil ~lookup_id e1 typ) + | Exn e -> + Exception (of_sil ~lookup_id e typ) + | Const c -> + Constant c + | Cast (cast_typ, e) -> + Cast (cast_typ, of_sil ~lookup_id e typ) + | Sizeof (sizeof_typ, dynamic_length, _) -> + Sizeof (sizeof_typ, Option.map ~f:(fun e -> of_sil ~lookup_id e typ) dynamic_length) + | Closure closure -> + let environment = + List.map + ~f:(fun (value, pvar, typ) -> + AccessPath.base_of_pvar pvar typ, of_sil ~lookup_id value typ) + closure.captured_vars in + Closure (closure.name, environment) + | Lvar _ | Lfield _ | Lindex _ -> + match AccessPath.of_lhs_exp exp typ ~f_resolve_id:lookup_id with + | Some access_path -> + AccessPath access_path + | None -> + failwithf "Couldn't convert var/field/index expression %a to access path" Exp.pp exp diff --git a/infer/src/IR/HilExp.mli b/infer/src/IR/HilExp.mli new file mode 100644 index 000000000..53b551a4c --- /dev/null +++ b/infer/src/IR/HilExp.mli @@ -0,0 +1,41 @@ +(* + * Copyright (c) 2017 - present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + *) + +open! IStd + +module F = Format + +type t = + | AccessPath of AccessPath.Raw.t + (** access path (e.g., x.f.g or x[i]) *) + | UnaryOperator of Unop.t * t * Typ.t option + (** Unary operator with type of the result if known *) + | BinaryOperator of Binop.t * t * t + (** Binary operator *) + | Exception of t + (** Exception *) + | Closure of Typ.Procname.t * (AccessPath.base * t) list + (** Name of function + environment *) + | Constant of Const.t + (** Constants *) + | Cast of Typ.t * t + (** Type cast *) + | Sizeof of Typ.t * t option + (** C-style sizeof(), and also used to treate a type as an expression. Refer to [Exp] module for + canonical documentation *) +[@@deriving compare] + +val pp : F.formatter -> t -> unit + +(** Convert SIL expression to HIL expression *) +val of_sil : lookup_id:(Var.t -> AccessPath.Raw.t option) -> Exp.t -> Typ.t -> t + +(** Get all the access paths used in the given HIL expression, including duplicates if a path is + used more than once. *) +val get_access_paths : t -> AccessPath.Raw.t list