This file is indexed.

/usr/lib/ocaml/compiler-libs/flambda.mli is in ocaml-compiler-libs 4.05.0-10ubuntu1.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
(**************************************************************************)
(*                                                                        *)
(*                                 OCaml                                  *)
(*                                                                        *)
(*                       Pierre Chambart, OCamlPro                        *)
(*           Mark Shinwell and Leo White, Jane Street Europe              *)
(*                                                                        *)
(*   Copyright 2013--2016 OCamlPro SAS                                    *)
(*   Copyright 2014--2016 Jane Street Group LLC                           *)
(*                                                                        *)
(*   All rights reserved.  This file is distributed under the terms of    *)
(*   the GNU Lesser General Public License version 2.1, with the          *)
(*   special exception on linking described in the file LICENSE.          *)
(*                                                                        *)
(**************************************************************************)

[@@@ocaml.warning "+a-4-9-30-40-41-42"]

(** Intermediate language used for tree-based analysis and optimization. *)

(** Whether the callee in a function application is known at compile time. *)
type call_kind =
  | Indirect
  | Direct of Closure_id.t

(** Simple constants.  ("Structured constants" are rewritten to invocations
    of [Pmakeblock] so that they easily take part in optimizations.) *)
type const =
  | Int of int
  | Char of char
  (** [Char] is kept separate from [Int] to improve printing *)
  | Const_pointer of int
  (** [Const_pointer] is an immediate value of a type whose values may be
     boxed (typically a variant type with both constant and non-constant
     constructors). *)

(** The application of a function to a list of arguments. *)
type apply = {
  (* CR-soon mshinwell: rename func -> callee, and
     lhs_of_application -> callee *)
  func : Variable.t;
  args : Variable.t list;
  kind : call_kind;
  dbg : Debuginfo.t;
  inline : Lambda.inline_attribute;
  (** Instructions from the source code as to whether the callee should
      be inlined. *)
  specialise : Lambda.specialise_attribute;
  (** Instructions from the source code as to whether the callee should
      be specialised. *)
}

(** The update of a mutable variable.  Mutable variables are distinct from
    immutable variables in Flambda. *)
type assign = {
  being_assigned : Mutable_variable.t;
  new_value : Variable.t;
}

(** The invocation of a method. *)
type send = {
  kind : Lambda.meth_kind;
  meth : Variable.t;
  obj : Variable.t;
  args : Variable.t list;
  dbg : Debuginfo.t;
}

(** For details on these types, see projection.mli. *)
type project_closure = Projection.project_closure
type move_within_set_of_closures = Projection.move_within_set_of_closures
type project_var = Projection.project_var

(** See [free_vars] and [specialised_args], below. *)
(* CR-someday mshinwell: move to separate module and make [Identifiable].
  (Or maybe nearly Identifiable; having a special map that enforces invariants
  might be good.) *)
type specialised_to = {
  var : Variable.t;
  (** The "outer variable". *)
  projection : Projection.t option;
  (** The [projecting_from] value (see projection.mli) of any [projection]
      must be another free variable or specialised argument (depending on
      whether this record type is involved in [free_vars] or
      [specialised_args] respectively) in the same set of closures.
      As such, this field describes a relation of projections between
      either the [free_vars] or the [specialised_args]. *)
}

(** Flambda terms are partitioned in a pseudo-ANF manner; many terms are
    required to be [let]-bound.  This in particular ensures there is always
    a variable name for an expression that may be lifted out (for example
    if it is found to be constant).
    Note: All bound variables in Flambda terms must be distinct.
    [Flambda_invariants] verifies this. *)
type t =
  | Var of Variable.t
  | Let of let_expr
  | Let_mutable of let_mutable
  | Let_rec of (Variable.t * named) list * t
  (** CR-someday lwhite: give Let_rec the same fields as Let. *)
  | Apply of apply
  | Send of send
  | Assign of assign
  | If_then_else of Variable.t * t * t
  | Switch of Variable.t * switch
  | String_switch of Variable.t * (string * t) list * t option
  (** Restrictions on [Lambda.Lstringswitch] also apply to [String_switch]. *)
  | Static_raise of Static_exception.t * Variable.t list
  | Static_catch of Static_exception.t * Variable.t list * t * t
  | Try_with of t * Variable.t * t
  | While of t * t
  | For of for_loop
  | Proved_unreachable

(** Values of type [named] will always be [let]-bound to a [Variable.t]. *)
and named =
  | Symbol of Symbol.t
  | Const of const
  | Allocated_const of Allocated_const.t
  | Read_mutable of Mutable_variable.t
  | Read_symbol_field of Symbol.t * int
  (** During the lifting of [let] bindings to [program] constructions after
      closure conversion, we generate symbols and their corresponding
      definitions (which may or may not be constant), together with field
      accesses to such symbols.  We would like it to be the case that such
      field accesses are simplified to the relevant component of the
      symbol concerned.  (The rationale is to generate efficient code and
      share constants as expected: see e.g. tests/asmcomp/staticalloc.ml.)
      The components of the symbol would be identified by other symbols.
      This sort of access pattern is feasible because the top-level structure
      of symbols is statically allocated and fixed at compile time.
      It may seem that [Prim (Pfield, ...)] expressions could be used to
      perform the field accesses.  However for simplicity, to avoid having to
      keep track of properties of individual fields of blocks,
      [Inconstant_idents] never deems a [Prim (Pfield, ...)] expression to be
      constant.  This would in general prevent field accesses to symbols from
      being simplified in the way we would like, since [Lift_constants] would
      not assign new symbols (i.e. the things we would like to simplify to)
      to the various projections from the symbols in question.
      To circumvent this problem we use [Read_symbol_field] when generating
      projections from the top level of symbols.  Owing to the properties of
      symbols described above, such expressions may be eligible for declaration
      as constant by [Inconstant_idents] (and thus themselves lifted to another
      symbol), without any further complication.
      [Read_symbol_field] may only be used when the definition of the symbol
      is in scope in the [program].  For external unresolved symbols, [Pfield]
      may still be used; it will be changed to [Read_symbol_field] by
      [Inline_and_simplify] when (and if) the symbol is imported. *)
  | Set_of_closures of set_of_closures
  | Project_closure of project_closure
  | Move_within_set_of_closures of move_within_set_of_closures
  | Project_var of project_var
  | Prim of Lambda.primitive * Variable.t list * Debuginfo.t
  | Expr of t  (** ANF escape hatch. *)

(* CR-someday mshinwell: use [letcont]-style construct to remove e.g.
   [While] and [For]. *)
(* CR-someday mshinwell: try to produce a tighter definition of a "switch"
   (and translate to that earlier) so that middle- and back-end code for
   these can be reduced. *)
(* CR-someday mshinwell: remove [Expr], but to do this easily would probably
   require a continuation-binding construct. *)
(* CR-someday mshinwell: Since we lack expression identifiers on every term,
   we should probably introduce [Mutable_var] into [named] if we introduce
   more complicated analyses on these in the future.  Alternatively, maybe
   consider removing mutable variables altogether. *)

and let_expr = private {
  var : Variable.t;
  defining_expr : named;
  body : t;
  (* CR-someday mshinwell: we could consider having these be keys into some
     kind of global cache, to reduce memory usage. *)
  free_vars_of_defining_expr : Variable.Set.t;
  (** A cache of the free variables in the defining expression of the [let]. *)
  free_vars_of_body : Variable.Set.t;
  (** A cache of the free variables of the body of the [let].  This is an
      important optimization. *)
}

and let_mutable = {
  var : Mutable_variable.t;
  initial_value : Variable.t;
  contents_kind : Lambda.value_kind;
  body : t;
}

(** The representation of a set of function declarations (possibly mutually
    recursive).  Such a set encapsulates the declarations themselves,
    information about their defining environment, and information used
    specifically for optimization.
    Before a function can be applied it must be "projected" from a set of
    closures to yield a "closure".  This is done using [Project_closure]
    (see above).  Given a closure, not only can it be applied, but information
    about its defining environment can be retrieved (using [Project_var],
    see above).
    At runtime, a [set_of_closures] corresponds to an OCaml value with tag
    [Closure_tag] (possibly with inline [Infix_tag](s)).  As an optimization,
    an operation ([Move_within_set_of_closures]) is provided (see above)
    which enables one closure within a set to be located given another
    closure in the same set.  This avoids keeping a pointer to the whole set
    of closures alive when compiling, for example, mutually-recursive
    functions.
*)
and set_of_closures = private {
  function_decls : function_declarations;
  (* CR-soon mshinwell: consider renaming [free_vars].  Also, it's still really
     confusing which side of this map to use when.  "Vars bound by the
     closure" is the domain.
     Another example of when this is confusing:
      let bound_vars_approx =
        Variable.Map.map (Env.find_approx env) set.free_vars
      in
     in [Build_export_info]. *)
  (* CR-soon mshinwell: I'd like to arrange these maps so that it's impossible
     to put invalid projection information into them (in particular, so that
     we enforce that the relation stays within the domain of the map). *)
  free_vars : specialised_to Variable.Map.t;
  (** Mapping from all variables free in the body of the [function_decls] to
      variables in scope at the definition point of the [set_of_closures].
      The domain of this map is sometimes known as the "variables bound by
      the closure". *)
  specialised_args : specialised_to Variable.Map.t;
  (** Parameters whose corresponding arguments are known to always alias a
      particular value.  These are the only parameters that may, during
      [Inline_and_simplify], have non-unknown approximations.

      An argument may only be specialised to a variable in the scope of the
      corresponding set of closures declaration.  Usually, that variable
      itself also appears in the position of the specialised argument at
      all call sites of the function.  However it may also be the case (for
      example in code generated as a result of [Augment_specialised_args])
      that the various call sites of such a function have differing
      variables in the position of the specialised argument.  This is
      permissible *so long as it is certain they all alias the same value*.
      Great care must be taken in transformations that result in this
      situation since there are no invariant checks for correctness.

      As an example, supposing all call sites of f are represented here:
        [let x = ... in
         let f a b c = ... in
         let y = ... in
         f x y 1;
         f x y 1]
      the specialised arguments of f can (but does not necessarily) contain
      the association [a] -> [x], but cannot contain [b] -> [y] because [f]
      is not in the scope of [y]. If f were the recursive function
      [let rec f a b c = f a 1 2 in], [a] -> [x] would still be a valid
      specialised argument because all recursive calls maintain the invariant.

      This information is used for optimization purposes, if such a binding is
      known, it is possible to specialise the body of the function according
      to its parameter. This is usually introduced when specialising a
      recursive function, for instance.
        [let rec map f = function
           | [] -> []
           | h :: t -> f h :: map f t
         let map_succ l =
           let succ x = x + 1 in
           map succ l]
      [map] can be duplicated in [map_succ] to be specialised for the argument
      [f]. This will result in
        [let map_succ l =
           let succ x = x + 1 in
           let rec map f = function
             | [] -> []
             | h :: t -> f h :: map f t in
           map succ l]
      with map having [f] -> [succ] in its [specialised_args] field.

      Specialised argument information for arguments that are used must
      never be erased.  This ensures that specialised arguments whose
      approximations describe closures maintain those approximations, which
      is essential to transport the closure freshening information to the
      point of use (e.g. a [Project_var] from such an argument).
  *)
  direct_call_surrogates : Variable.t Variable.Map.t;
  (** If [direct_call_surrogates] maps [fun_var1] to [fun_var2] then direct
      calls to [fun_var1] should be redirected to [fun_var2].  This is used
      to reduce the overhead of transformations that introduce wrapper
      functions (which will be inlined at direct call sites, but will
      penalise indirect call sites).
      [direct_call_surrogates] may not be transitively closed. *)
}

and function_declarations = private {
  set_of_closures_id : Set_of_closures_id.t;
  (** An identifier (unique across all Flambda trees currently in memory)
      of the set of closures associated with this set of function
      declarations. *)
  set_of_closures_origin : Set_of_closures_origin.t;
  (** An identifier of the original set of closures on which this set of
      function declarations is based.  Used to prevent different
      specialisations of the same functions from being inlined/specialised
      within each other. *)
  funs : function_declaration Variable.Map.t;
  (** The function(s) defined by the set of function declarations.  The
      keys of this map are often referred to in the code as "fun_var"s. *)
}

and function_declaration = private {
  params : Variable.t list;
  body : t;
  (* CR-soon mshinwell: inconsistent naming free_variables/free_vars here and
     above *)
  free_variables : Variable.Set.t;
  (** All variables free in the *body* of the function.  For example, a
      variable that is bound as one of the function's parameters will still
      be included in this set.  This field is present as an optimization. *)
  free_symbols : Symbol.Set.t;
  (** All symbols that occur in the function's body.  (Symbols can never be
      bound in a function's body; the only thing that binds symbols is the
      [program] constructions below.) *)
  stub : bool;
  (** A stub function is a generated function used to prepare arguments or
      return values to allow indirect calls to functions with a special calling
      convention.  For instance indirect calls to tuplified functions must go
      through a stub.  Stubs will be unconditionally inlined. *)
  dbg : Debuginfo.t;
  (** Debug info for the function declaration. *)
  inline : Lambda.inline_attribute;
  (** Inlining requirements from the source code. *)
  specialise : Lambda.specialise_attribute;
  (** Specialising requirements from the source code. *)
  is_a_functor : bool;
  (** Whether the function is known definitively to be a functor. *)
}

(** Equivalent to the similar type in [Lambda]. *)
and switch = {
  numconsts : Numbers.Int.Set.t; (** Integer cases *)
  consts : (int * t) list; (** Integer cases *)
  numblocks : Numbers.Int.Set.t; (** Number of tag block cases *)
  blocks : (int * t) list; (** Tag block cases *)
  failaction : t option; (** Action to take if none matched *)
}

(** Equivalent to the similar type in [Lambda]. *)
and for_loop = {
  bound_var : Variable.t;
  from_value : Variable.t;
  to_value : Variable.t;
  direction : Asttypes.direction_flag;
  body : t
}

(** Like a subset of [Flambda.named], except that instead of [Variable.t]s we
    have [Symbol.t]s, and everything is a constant (i.e. with a fixed value
    known at compile time).  Values of this type describe constants that will
    be directly assigned to symbols in the object file (see below). *)
and constant_defining_value =
  | Allocated_const of Allocated_const.t
    (** A single constant.  These are never "simple constants" (type [const])
        but instead more complicated constructions. *)
  | Block of Tag.t * constant_defining_value_block_field list
    (** A pre-allocated block full of constants (either simple constants
        or references to other constants, see below). *)
  | Set_of_closures of set_of_closures
    (** A closed (and thus constant) set of closures.  (That is to say,
        [free_vars] must be empty.) *)
  | Project_closure of Symbol.t * Closure_id.t
    (** Selection of one closure from a constant set of closures.
        Analogous to the equivalent operation on expressions. *)

and constant_defining_value_block_field =
  | Symbol of Symbol.t
  | Const of const

module Constant_defining_value :
  Identifiable.S with type t = constant_defining_value

type expr = t

(** A "program" is the contents of one compilation unit.  It describes the
    various values that are assigned to symbols (and in some cases fields of
    such symbols) in the object file.  As such, it is closely related to
    the compilation of toplevel modules. *)
type program_body =
  | Let_symbol of Symbol.t * constant_defining_value * program_body
  (** Define the given symbol to have the given constant value. *)
  | Let_rec_symbol of (Symbol.t * constant_defining_value) list * program_body
  (** As for [Let_symbol], but recursive.  This is needed to treat examples
      like this, where a constant set of closures is lifted to toplevel:

        let rec f x = f x

      After lifting this produces (in pseudo-Flambda):

        Let_rec_symbol set_of_closures_symbol =
          (Set_of_closures { f x ->
            let applied_function = Symbol f_closure in
            Apply (applied_function, x) })
        and f_closure = Project_closure (set_of_closures_symbol, f)

      Use of [Let_rec_symbol], by virtue of the special handling in
      [Inline_and_simplify.define_let_rec_symbol_approx], enables the
      approximation of the set of closures to be present in order to
      correctly simplify the [Project_closure] construction.  (See
      [Inline_and_simplify.simplify_project_closure] for that part.) *)
  | Initialize_symbol of Symbol.t * Tag.t * t list * program_body
  (** Define the given symbol as a constant block of the given size and
      tag; but with a possibly non-constant initializer.  The initializer
      will be executed at most once (from the entry point of the compilation
      unit). *)
  | Effect of t * program_body
  (** Cause the given expression, which may have a side effect, to be
      executed.  The resulting value is discarded.  [Effect] constructions
      are never re-ordered. *)
  | End of Symbol.t
  (** [End] accepts the root symbol: the only symbol that can never be
      eliminated. *)

type program = {
  imported_symbols : Symbol.Set.t;
  program_body : program_body;
}

(** Compute the free variables of a term.  (This is O(1) for [Let]s).
    If [ignore_uses_as_callee], all free variables inside [Apply] expressions
    are ignored.  Likewise [ignore_uses_in_project_var] for [Project_var]
    expressions.
*)
val free_variables
   : ?ignore_uses_as_callee:unit
  -> ?ignore_uses_as_argument:unit
  -> ?ignore_uses_in_project_var:unit
  -> t
  -> Variable.Set.t

(** Compute the free variables of a named expression. *)
val free_variables_named
   : ?ignore_uses_in_project_var:unit
  -> named
  -> Variable.Set.t

(** Compute _all_ variables occurring inside an expression. *)
val used_variables
   : ?ignore_uses_as_callee:unit
  -> ?ignore_uses_as_argument:unit
  -> ?ignore_uses_in_project_var:unit
  -> t
  -> Variable.Set.t

(** Compute _all_ variables occurring inside a named expression. *)
val used_variables_named
   : ?ignore_uses_in_project_var:unit
  -> named
  -> Variable.Set.t

val free_symbols : expr -> Symbol.Set.t

val free_symbols_named : named -> Symbol.Set.t

val free_symbols_program : program -> Symbol.Set.t

(** Used to avoid exceeding the stack limit when handling expressions with
    multiple consecutive nested [Let]-expressions.  This saves rewriting large
    simplification functions in CPS.  This function provides for the
    rewriting or elimination of expressions during the fold. *)
val fold_lets_option
   : t
  -> init:'a
  -> for_defining_expr:('a -> Variable.t -> named -> 'a * Variable.t * named)
  -> for_last_body:('a -> t -> t * 'b)
  (* CR-someday mshinwell: consider making [filter_defining_expr]
     optional *)
  -> filter_defining_expr:('b -> Variable.t -> named -> Variable.Set.t ->
                           'b * Variable.t * named option)
  -> t * 'b

(** Like [fold_lets_option], but just a map. *)
val map_lets
   : t
  -> for_defining_expr:(Variable.t -> named -> named)
  -> for_last_body:(t -> t)
  -> after_rebuild:(t -> t)
  -> t

(** Like [map_lets], but just an iterator. *)
val iter_lets
   : t
  -> for_defining_expr:(Variable.t -> named -> unit)
  -> for_last_body:(t -> unit)
  -> for_each_let:(t -> unit)
  -> unit

(** Creates a [Let] expression.  (This computes the free variables of the
    defining expression and the body.) *)
val create_let : Variable.t -> named -> t -> t

(** Apply the specified function [f] to the defining expression of the given
    [Let]-expression, returning a new [Let]. *)
val map_defining_expr_of_let : let_expr -> f:(named -> named) -> t

(** A module for the manipulation of terms where the recomputation of free
    variable sets is to be kept to a minimum. *)
module With_free_variables : sig
  type 'a t

  (** O(1) time. *)
  val of_defining_expr_of_let : let_expr -> named t

  (** O(1) time. *)
  val of_body_of_let : let_expr -> expr t

  (** Takes the time required to calculate the free variables of the given
      term (proportional to the size of the term, except that the calculation
      for [Let] is O(1)). *)
  val of_expr : expr -> expr t

  val of_named : named -> named t

  (** Takes the time required to calculate the free variables of the given
      [expr]. *)
  val create_let_reusing_defining_expr
     : Variable.t
    -> named t
    -> expr
    -> expr

  (** Takes the time required to calculate the free variables of the given
      [named]. *)
  val create_let_reusing_body
     : Variable.t
    -> named
    -> expr t
    -> expr

  (** O(1) time. *)
  val create_let_reusing_both
     : Variable.t
    -> named t
    -> expr t
    -> expr

  (** The equivalent of the [Expr] constructor. *)
  val expr : expr t -> named t

  val contents : 'a t -> 'a

  (** O(1) time. *)
  val free_variables : _ t -> Variable.Set.t
end

(** Create a function declaration.  This calculates the free variables and
    symbols occurring in the specified [body]. *)
val create_function_declaration
   : params:Variable.t list
  -> body:t
  -> stub:bool
  -> dbg:Debuginfo.t
  -> inline:Lambda.inline_attribute
  -> specialise:Lambda.specialise_attribute
  -> is_a_functor:bool
  -> function_declaration

(** Create a set of function declarations given the individual declarations. *)
val create_function_declarations
   : funs:function_declaration Variable.Map.t
  -> function_declarations

(** Create a set of function declarations based on another set of function
    declarations. *)
val update_function_declarations
   : function_declarations
  -> funs:function_declaration Variable.Map.t
  -> function_declarations

val import_function_declarations_for_pack
   : function_declarations
  -> (Set_of_closures_id.t -> Set_of_closures_id.t)
  -> (Set_of_closures_origin.t -> Set_of_closures_origin.t)
  -> function_declarations

(** Create a set of closures.  Checks are made to ensure that [free_vars]
    and [specialised_args] are reasonable. *)
val create_set_of_closures
   : function_decls:function_declarations
  -> free_vars:specialised_to Variable.Map.t
  -> specialised_args:specialised_to Variable.Map.t
  -> direct_call_surrogates:Variable.t Variable.Map.t
  -> set_of_closures

(** Given a function declaration, find which of its parameters (if any)
    are used in the body. *)
val used_params : function_declaration -> Variable.Set.t

type maybe_named =
  | Is_expr of t
  | Is_named of named

(** This function is designed for the internal use of [Flambda_iterators].
    See that module for iterators to be used over Flambda terms. *)
val iter_general
   : toplevel:bool
  -> (t -> unit)
  -> (named -> unit)
  -> maybe_named
  -> unit

val print : Format.formatter -> t -> unit

val print_named : Format.formatter -> named -> unit

val print_program : Format.formatter -> program -> unit

val print_const : Format.formatter -> const -> unit

val print_constant_defining_value
   : Format.formatter
  -> constant_defining_value
  -> unit

val print_function_declaration
   : Format.formatter
  -> Variable.t * function_declaration
  -> unit

val print_function_declarations
   : Format.formatter
  -> function_declarations
  -> unit

val print_project_closure
   : Format.formatter
  -> project_closure
  -> unit

val print_move_within_set_of_closures
   : Format.formatter
  -> move_within_set_of_closures
  -> unit

val print_project_var
   : Format.formatter
  -> project_var
  -> unit

val print_set_of_closures
   : Format.formatter
  -> set_of_closures
  -> unit

val print_specialised_to
   : Format.formatter
  -> specialised_to
  -> unit

val equal_specialised_to
   : specialised_to
  -> specialised_to
  -> bool

val compare_project_var : project_var -> project_var -> int

val compare_move_within_set_of_closures
   : move_within_set_of_closures
  -> move_within_set_of_closures
  -> int

val compare_project_closure : project_closure -> project_closure -> int