jon.recoil.org

Module Cfg

val verbose : bool Stdlib.ref
include module type of struct include Cfg_intf.S end
type func_call_operation = Cfg_intf.S.func_call_operation =
  1. | Indirect of Cmm.symbol list option
  2. | Direct of Cmm.symbol
type external_call_operation = Cfg_intf.S.external_call_operation = {
  1. func_symbol : string;
  2. alloc : bool;
  3. effects : Cmm.effects;
  4. ty_res : Cmm.machtype;
  5. ty_args : Cmm.exttype list;
  6. stack_ofs : int;
  7. stack_align : Cmm.stack_align;
}
type prim_call_operation = Cfg_intf.S.prim_call_operation =
  1. | External of Cfg.external_call_operation
  2. | Probe of {
    1. name : string;
    2. handler_code_sym : string;
    3. enabled_at_init : bool;
    }
type bool_test = Cfg_intf.S.bool_test = {
  1. ifso : Label.t;
    (*

    if test is true goto ifso label

    *)
  2. ifnot : Label.t;
    (*

    if test is false goto ifnot label

    *)
}
type int_test = Cfg_intf.S.int_test = {
  1. lt : Label.t;
    (*

    if x < y (resp. x < n) goto lt label

    *)
  2. eq : Label.t;
    (*

    if x = y (resp. x = n) goto eq label

    *)
  3. gt : Label.t;
    (*

    if x > y (resp. x > n) goto gt label

    *)
  4. is_signed : Scalar.Signedness.t;
  5. imm : int option;
}

int_test represents all possible outcomes of a comparison between two integers. When imm field is None, compare variables x and y, specified by the arguments of the enclosing instruction. When imm field is Some n, compare variable x and immediate n. This corresponds to Mach.Iinttest and Mach.Iinttest_imm in the compiler.

type float_test = Cfg_intf.S.float_test = {
  1. width : Cmm.float_width;
  2. lt : Label.t;
  3. eq : Label.t;
  4. gt : Label.t;
  5. uo : Label.t;
    (*

    if at least one of x or y is NaN

    *)
}

float_test represents possible outcomes of comparison between arguments x and y of type float. It is not enough to check "=,<,>" because possible outcomes of comparison include "unordered" (see e.g. x86-64 emitter) when the arguments involve NaNs.

type 'a instruction = 'a Cfg_intf.S.instruction = {
  1. desc : 'a;
  2. id : InstructionId.t;
  3. mutable arg : Reg.t array;
  4. mutable res : Reg.t array;
  5. mutable dbg : Debuginfo.t;
  6. mutable fdo : Fdo_info.t;
  7. mutable live : Reg.Set.t;
  8. mutable stack_offset : int;
  9. mutable available_before : Reg_availability_set.t;
  10. mutable available_across : Reg_availability_set.t;
    (*

    The availability sets will be set to Unreachable prior to the availability analysis having run.

    *)
}
type basic = Cfg_intf.S.basic =
  1. | Op of Operation.t
  2. | Reloadretaddr
    (*

    This instruction loads the return address from a predefined hidden address (e.g. bottom of the current frame) and stores it in a special hidden register. It can use standard registers for that purpose. They are defined in Proc.destroyed_at_reloadretaddr.

    *)
  3. | Pushtrap of {
    1. lbl_handler : Label.t;
    }
  4. | Poptrap of {
    1. lbl_handler : Label.t;
    }
  5. | Prologue
  6. | Epilogue
  7. | Stack_check of {
    1. max_frame_size_bytes : int;
    }
type 'a with_label_after = 'a Cfg_intf.S.with_label_after = {
  1. op : 'a;
  2. label_after : Label.t;
}
type terminator = Cfg_intf.S.terminator =
  1. | Never
  2. | Always of Label.t
  3. | Parity_test of Cfg.bool_test
    (*

    Check if the argument is even or odd

    *)
  4. | Truth_test of Cfg.bool_test
    (*

    Check if the argument is true or false.

    *)
  5. | Float_test of Cfg.float_test
  6. | Int_test of Cfg.int_test
  7. | Switch of Label.t array
  8. | Return
  9. | Raise of Lambda.raise_kind
  10. | Tailcall_self of {
    1. destination : Label.t;
    }
  11. | Tailcall_func of Cfg.func_call_operation
  12. | Call_no_return of Cfg.external_call_operation
  13. | Call of Cfg.func_call_operation Cfg.with_label_after
  14. | Prim of Cfg.prim_call_operation Cfg.with_label_after
type basic_or_terminator = Cfg_intf.S.basic_or_terminator =
  1. | Basic of Cfg.basic
  2. | Terminator of Cfg.terminator
type basic_instruction_list = Cfg.basic Cfg.instruction Oxcaml_utils.Doubly_linked_list.t
type basic_block = {
  1. mutable start : Label.t;
  2. body : Cfg.basic_instruction_list;
  3. mutable terminator : Cfg.terminator Cfg.instruction;
  4. mutable predecessors : Label.Set.t;
    (*

    All predecessors, both normal and exceptional paths.

    *)
  5. mutable stack_offset : int;
    (*

    Stack offset of the start of the block. Used for emitting adjust trap on edges from one block to the next.

    *)
  6. mutable exn : Label.t option;
    (*

    All possible handlers of a raise that (1) can be triggered either by an explicit raise, or instructions such as calls and allocations, that appear(s) in this block; and (2) are within the same function. exns is a subset of the trap handler block labels of the cfg.

    *)
  7. mutable can_raise : bool;
    (*

    Does this block contain any instruction that can raise, such as a call, bounds check, allocation, or an explicit raise?

    *)
  8. mutable is_trap_handler : bool;
    (*

    Is this block a trap handler (i.e. is it an exn successor of another block) or not?

    *)
  9. mutable cold : bool;
}
type codegen_option =
  1. | Reduce_code_size
  2. | No_CSE
  3. | Use_linscan_regalloc
  4. | Use_regalloc of Clflags.Register_allocator.t
  5. | Use_regalloc_param of string list
  6. | Cold
  7. | Assume_zero_alloc of {
    1. strict : bool;
    2. never_returns_normally : bool;
    3. never_raises : bool;
    4. loc : Location.t;
    }
  8. | Check_zero_alloc of {
    1. strict : bool;
    2. loc : Location.t;
    3. custom_error_msg : string option;
    }
val of_cmm_codegen_option : Cmm.codegen_option list -> Cfg.codegen_option list
type t = {
  1. blocks : Cfg.basic_block Label.Tbl.t;
    (*

    Map from labels to blocks

    *)
  2. fun_name : string;
    (*

    Function name, used for printing messages

    *)
  3. fun_args : Reg.t array;
    (*

    Function arguments. When Cfg is constructed from Linear, this information is not needed (Linear.fundecl does not have fun_args field) and fun_args is an empty array as a dummy value.

    *)
  4. fun_codegen_options : Cfg.codegen_option list;
    (*

    Code generation options passed from Cmm.

    *)
  5. fun_dbg : Debuginfo.t;
    (*

    Dwarf debug info for function entry.

    *)
  6. entry_label : Label.t;
    (*

    This label must be the first in all layouts of this cfg.

    *)
  7. fun_contains_calls : bool;
    (*

    Precomputed during selection and poll insertion.

    *)
  8. fun_num_stack_slots : int Stack_class.Tbl.t;
    (*

    Precomputed at register allocation time

    *)
  9. fun_poll : Lambda.poll_attribute;
  10. next_instruction_id : InstructionId.sequence;
  11. fun_ret_type : Cmm.machtype;
    (*

    Function return type. As in fun_args, this value is not used when starting from Linear.

    *)
  12. mutable allowed_to_be_irreducible : bool;
  13. mutable register_locations_are_set : bool;
}

Control Flow Graph of a function.

val create : fun_name:string -> fun_args:Reg.t array -> fun_codegen_options:Cfg.codegen_option list -> fun_dbg:Debuginfo.t -> fun_contains_calls:bool -> fun_num_stack_slots:int Stack_class.Tbl.t -> fun_poll:Lambda.poll_attribute -> next_instruction_id:InstructionId.sequence -> fun_ret_type:Cmm.machtype -> allowed_to_be_irreducible:bool -> Cfg.t
val fun_name : Cfg.t -> string
val entry_label : Cfg.t -> Label.t
val predecessor_labels : Cfg.basic_block -> Label.t list
val successor_labels : normal:bool -> exn:bool -> Cfg.basic_block -> Label.Set.t

exn does not account for exceptional flow from the block that goes outside of the function.

val replace_successor_labels : Cfg.t -> normal:bool -> exn:bool -> Cfg.basic_block -> f:(Label.t -> Label.t) -> unit
val can_raise_interproc : Cfg.basic_block -> bool

Returns true iff the passed block raises an exn that is not handled in this function, can_raise_interproc implies can_raise but not necessarily vice versa.

val first_instruction_id : Cfg.basic_block -> InstructionId.t
val first_instruction_stack_offset : Cfg.basic_block -> int
val mem_block : Cfg.t -> Label.t -> bool
val add_block_exn : Cfg.t -> Cfg.basic_block -> unit
val remove_blocks : Cfg.t -> Label.Set.t -> unit
val get_block : Cfg.t -> Label.t -> Cfg.basic_block option
val get_block_exn : Cfg.t -> Label.t -> Cfg.basic_block
val iter_blocks_dfs : Cfg.t -> f:(Label.t -> Cfg.basic_block -> unit) -> unit
val iter_blocks : Cfg.t -> f:(Label.t -> Cfg.basic_block -> unit) -> unit
val fold_blocks : Cfg.t -> f:(Label.t -> Cfg.basic_block -> 'a -> 'a) -> init:'a -> 'a
val fold_body_instructions : Cfg.t -> f:('a -> Cfg.basic Cfg.instruction -> 'a) -> init:'a -> 'a
val register_predecessors_for_all_blocks : Cfg.t -> unit

Printing

val print_terminator : Stdlib.Format.formatter -> Cfg.terminator Cfg.instruction -> unit
val print_instruction' : ?print_reg:(Stdlib.Format.formatter -> Reg.t -> unit) -> Stdlib.Format.formatter -> [ `Basic of Cfg.basic Cfg.instruction | `Terminator of Cfg.terminator Cfg.instruction ] -> unit
val print_instruction : Stdlib.Format.formatter -> [ `Basic of Cfg.basic Cfg.instruction | `Terminator of Cfg.terminator Cfg.instruction ] -> unit
val can_raise_terminator : Cfg.terminator -> bool
val is_pure_terminator : Cfg.terminator -> bool
val is_never_terminator : Cfg.terminator -> bool
val is_return_terminator : Cfg.terminator -> bool
val is_pure_basic : Cfg.basic -> bool
val is_noop_move : Cfg.basic Cfg.instruction -> bool
val is_alloc : Cfg.basic Cfg.instruction -> bool
val is_poll : Cfg.basic Cfg.instruction -> bool
val is_end_region : Cfg.basic -> bool
val set_stack_offset : 'a Cfg.instruction -> int -> unit
val set_live : 'a Cfg.instruction -> Reg.Set.t -> unit
val dump_basic : Stdlib.Format.formatter -> Cfg.basic -> unit
val dump_terminator : ?sep:string -> Stdlib.Format.formatter -> Cfg.terminator -> unit
val make_instruction : desc:'a -> ?arg:Reg.t array -> ?res:Reg.t array -> ?dbg:Debuginfo.t -> ?fdo:Fdo_info.t -> ?live:Reg.Set.t -> stack_offset:int -> id:InstructionId.t -> ?available_before:Reg_availability_set.t -> ?available_across:Reg_availability_set.t -> unit -> 'a Cfg.instruction
val make_instruction_from_copy : 'a Cfg.instruction -> desc:'b -> id:InstructionId.t -> ?arg:Reg.t array -> ?res:Reg.t array -> unit -> 'b Cfg.instruction
val make_empty_block : ?label:Label.t -> Cfg.terminator Cfg.instruction -> Cfg.basic_block
val basic_block_contains_calls : Cfg.basic_block -> bool

"Contains calls" in the traditional sense as used in upstream Selectgen.

val invalid_stack_offset : int