You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

245 lines
7.1 KiB

(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
(** Expressions
Pure (heap-independent) expressions are complex arithmetic,
bitwise-logical, etc. operations over literal values and registers. *)
type op1 =
| Signed of {bits: int}
(** [Ap1 (Signed {bits= n}, dst, arg)] is [arg] interpreted as an
[n]-bit signed integer and injected into the [dst] type. That is,
it two's-complement--decodes the low [n] bits of the infinite
two's-complement encoding of [arg]. The injection into [dst] is a
no-op, so [dst] must be an integer type with bitwidth at least
[n]. *)
| Unsigned of {bits: int}
(** [Ap1 (Unsigned {bits= n}, dst, arg)] is [arg] interpreted as an
[n]-bit unsigned integer and injected into the [dst] type. That
is, it unsigned-binary--decodes the low [n] bits of the infinite
two's-complement encoding of [arg]. The injection into [dst] is a
no-op, so [dst] must be an integer type with bitwidth greater than
[n]. *)
| Convert of {src: Typ.t}
(** [Ap1 (Convert {src}, dst, arg)] is [arg] converted from type [src]
to type [dst], possibly with loss of information. The [src] and
[dst] types must be [Typ.convertible] and must not both be
[Integer] types. *)
| Splat (** Iterated concatenation of a single byte *)
| Select of int (** Select an index from a record *)
[@@deriving compare, equal, hash, sexp]
type op2 =
| Eq (** Equal test *)
| Dq (** Disequal test *)
| Gt (** Greater-than test *)
| Ge (** Greater-than-or-equal test *)
| Lt (** Less-than test *)
| Le (** Less-than-or-equal test *)
| Ugt (** Unsigned greater-than test *)
| Uge (** Unsigned greater-than-or-equal test *)
| Ult (** Unsigned less-than test *)
| Ule (** Unsigned less-than-or-equal test *)
| Ord (** Ordered test (neither arg is nan) *)
| Uno (** Unordered test (some arg is nan) *)
| Add (** Addition *)
| Sub (** Subtraction *)
| Mul (** Multiplication *)
| Div (** Division, for integers result is truncated toward zero *)
| Rem
(** Remainder of division, satisfies [a = b * div a b + rem a b] and
for integers [rem a b] has same sign as [a], and [|rem a b| < |b|] *)
| Udiv (** Unsigned division *)
| Urem (** Remainder of unsigned division *)
| And (** Conjunction, boolean or bitwise *)
| Or (** Disjunction, boolean or bitwise *)
| Xor (** Exclusive-or, bitwise *)
| Shl (** Shift left, bitwise *)
| Lshr (** Logical shift right, bitwise *)
| Ashr (** Arithmetic shift right, bitwise *)
| Update of int (** Constant record with updated index *)
[@@deriving compare, equal, hash, sexp]
type op3 = Conditional (** If-then-else *)
[@@deriving compare, equal, hash, sexp]
type opN = Record (** Record (array / struct) constant *)
[@@deriving compare, equal, hash, sexp]
type t = private
| Reg of {id: int; name: string; typ: Typ.t} (** Virtual register *)
| Global of {name: string; typ: Typ.t [@ignore]} (** Global constant *)
| Function of {name: string; typ: Typ.t [@ignore]} (** Function name *)
| Label of {parent: string; name: string}
(** Address of named code block within parent function *)
| Integer of {data: Z.t; typ: Typ.t} (** Integer constant *)
| Float of {data: string; typ: Typ.t} (** Floating-point constant *)
| Ap1 of op1 * Typ.t * t
| Ap2 of op2 * Typ.t * t * t
| Ap3 of op3 * Typ.t * t * t * t
| ApN of opN * Typ.t * t iarray
[@@deriving compare, equal, hash, sexp]
val pp : t pp
include Invariant.S with type t := t
val demangle : (string -> string option) ref
(** Exp.Reg is re-exported as Reg *)
module Reg : sig
type exp := t
type t = private exp [@@deriving compare, equal, hash, sexp]
module Set : sig
include Set.S with type elt := t
include sig
type t [@@deriving hash, sexp]
end
with type t := t
val pp : t pp
end
val pp : t pp
include Invariant.S with type t := t
val of_exp : exp -> t option
val mk : Typ.t -> int -> string -> t
val id : t -> int
val name : t -> string
val typ : t -> Typ.t
end
(** Exp.Global is re-exported as Global *)
module Global : sig
type exp := t
type t = private exp [@@deriving compare, equal, hash, sexp]
module Set : sig
include Set.S with type elt := t
include sig
type t [@@deriving sexp]
end
with type t := t
val pp : t pp
end
val pp : t pp
include Invariant.S with type t := t
val of_exp : exp -> t option
val mk : Typ.t -> string -> t
val name : t -> string
val typ : t -> Typ.t
end
(** Exp.Function is re-exported as Function *)
module Function : sig
type exp := t
type t = private exp [@@deriving compare, equal, hash, sexp]
module Map : Map.S with type key := t
module Tbl : HashTable.S with type key := t
val pp : t pp
include Invariant.S with type t := t
val of_exp : exp -> t option
val mk : Typ.t -> string -> t
val counterfeit : string -> t
(** [compare] ignores [Function.typ], so it is possible to construct
[Function] names using a dummy type that compare equal to their
genuine counterparts. *)
val name : t -> string
val typ : t -> Typ.t
end
(** Construct *)
(* registers *)
val reg : Reg.t -> t
(* constants *)
val function_ : Function.t -> t
val global : Global.t -> t
val label : parent:string -> name:string -> t
val null : t
val bool : bool -> t
val true_ : t
val false_ : t
val integer : Typ.t -> Z.t -> t
val float : Typ.t -> string -> t
(* type conversions *)
val signed : int -> t -> to_:Typ.t -> t
val unsigned : int -> t -> to_:Typ.t -> t
val convert : Typ.t -> to_:Typ.t -> t -> t
(* comparisons *)
val eq : ?typ:Typ.t -> t -> t -> t
val dq : ?typ:Typ.t -> t -> t -> t
val gt : ?typ:Typ.t -> t -> t -> t
val ge : ?typ:Typ.t -> t -> t -> t
val lt : ?typ:Typ.t -> t -> t -> t
val le : ?typ:Typ.t -> t -> t -> t
val ugt : ?typ:Typ.t -> t -> t -> t
val uge : ?typ:Typ.t -> t -> t -> t
val ult : ?typ:Typ.t -> t -> t -> t
val ule : ?typ:Typ.t -> t -> t -> t
val ord : ?typ:Typ.t -> t -> t -> t
val uno : ?typ:Typ.t -> t -> t -> t
(* arithmetic *)
val add : ?typ:Typ.t -> t -> t -> t
val sub : ?typ:Typ.t -> t -> t -> t
val mul : ?typ:Typ.t -> t -> t -> t
val div : ?typ:Typ.t -> t -> t -> t
val rem : ?typ:Typ.t -> t -> t -> t
val udiv : ?typ:Typ.t -> t -> t -> t
val urem : ?typ:Typ.t -> t -> t -> t
(* boolean / bitwise *)
val and_ : ?typ:Typ.t -> t -> t -> t
val or_ : ?typ:Typ.t -> t -> t -> t
(* bitwise *)
val xor : ?typ:Typ.t -> t -> t -> t
val shl : ?typ:Typ.t -> t -> t -> t
val lshr : ?typ:Typ.t -> t -> t -> t
val ashr : ?typ:Typ.t -> t -> t -> t
(* if-then-else *)
val conditional : Typ.t -> cnd:t -> thn:t -> els:t -> t
(* sequences *)
val splat : Typ.t -> t -> t
(* records (struct / array values) *)
val record : Typ.t -> t iarray -> t
val select : Typ.t -> t -> int -> t
val update : Typ.t -> rcd:t -> int -> elt:t -> t
(** Traverse *)
val fold_exps : t -> 's -> f:(t -> 's -> 's) -> 's
val fold_regs : t -> 's -> f:(Reg.t -> 's -> 's) -> 's
(** Query *)
val is_true : t -> bool
val is_false : t -> bool