Module Asm_ir


module Asm_ir: sig  end
Abstract syntax tree with an assembly looking-like structure.
Author(s): Samuel Mimram

exception Asm_error of string
An error during the generation of the assembly.

type value =
| Int of int
| Bool of bool
Pseudo-typed values for assembly.

type var_type =
| Boolean
| Integer
| Pointer
| Other of int (*arrays, etc (the argument is its size)*)
| No_type (*no type was infered yet (this should not be generated)*)
Type of variables.
val sizeof : var_type -> int
Get the size in memory, in bytes, needed by a type.

type xflag =
| Aflag (*above (unsigned)*)
| Bflag (*below (unsigned)*)
| Eflag (*equal*)
| Zflag (*zero*)
| Gflag (*greater than (signed)*)
| Lflag (*less than (signed)*)
| Cflag (*carry*)
| Oflag (*overflow*)
| Pflag (*parity*)
| Sflag (*sign*)
| Vflag of variable (*the result is contained in a variable*)
Kinds of flags.

type flag = {
   flag_not : bool;
   flag_flag : xflag;
   flag_eq : bool;
}
A flag.

type register =
| Reg_int of int (*a register which can contain integers*)
| Reg_flag of flag (*flags of the processor*)
A register.

type stack_pos =
| Pos_base of int (*position is relative to the base pointer*)
| Pos_stack of int (*position is relative to the stack pointer*)
| Pos_label of string (*position is a label in the asm*)
| Pos_arr of (variable * variable * int * int) (*Pos_arr(b, v, n0, s) means &b + ((v) - n0) * s where s might be equal 1, 2, 4 or 8 (useful for arrays)*)
| Pos_rec of (variable * int) (*Pos_ref(b, k) means &b + k (useful for records)*)
| Pos_pointed of variable (*variable is pointed by an other variable*)
| Pos_none (*no position has been assigned yet*)
A position on the stack.

type variable_def = {
   mutable vd_ident : int; (*unique identifier*)
   mutable vd_pos : stack_pos Pervasives.ref; (*position, in bytes, relative to the frame pointer position*)
   mutable vd_type : var_type Pervasives.ref; (*type*)
   mutable vd_lex_depth : int Pervasives.ref; (*lexical depth*)
   mutable vd_value : value option; (*for constants*)
   mutable vd_on_the_stack : bool Pervasives.ref; (*should some space be allocated on the stack for the variable by default? (should be false for booleans and integers by default)*)
}
A variable definition.

The ref are here because they should be shared between variable definitions.


type variable = {
   mutable var_reg : register option; (*number of its register*)
   mutable var_def : variable_def; (*position of the variable on the stack*)
}
A variable.
val neg_flag : flag -> flag
Get the negated version of a flag.
val commute_flag : flag -> flag
Find the flag with arguments swapped (e.g. x < y ~ y > x).
val vd_counter : int Pervasives.ref
Fresh identifiers generator.
val new_var_def : var_type -> int -> variable_def
new_var_def type depth generates a new variable definition.
val new_var : variable_def -> variable
Create a new variable.
val new_const_int_var : int -> int -> variable
new_const_int_var n depth creates a new variable which is a constant integer equal to n.
val copy_var_def : variable_def -> variable_def
Get a copy of a variable definition.
val copy_var : variable -> variable
Get a copy of a variable.
val get_var_reg : variable -> register
Get the register in which a variable is stored.
val set_var_reg : variable -> register -> unit
val get_vd_type : variable_def -> var_type
val get_var_type : variable -> var_type
val get_vd_lex : variable_def -> int
Get the lexical depth of a variable definition.
val get_var_lex : variable -> int
Get the lexical depth of a variable.
val get_vd_pos : variable_def -> stack_pos
Get the position of a variable definition on the stack.
val get_var_pos : variable -> stack_pos
Get the position of a variable on the stack.
val get_vd_ots : variable_def -> bool
Is a variable definition on the stack?
val get_var_ots : variable -> bool
Is a variable on the stack?
val set_vd_ots : variable_def -> unit
val set_var_ots : variable -> unit
val get_vd_value : variable_def -> value option
val get_var_value : variable -> value option

type procedure = {
   proc_name : string; (*name of the procedure*)
   proc_args : variable_def list; (*arguments of the procedure*)
   mutable proc_vars : variable_def list; (*variables defined in the procedure (including temporary ones).*)
   mutable proc_value : base_block; (*first base block of the procedure*)
   mutable proc_lex_depth : int; (*lexical depth*)
   mutable proc_stack_size : int; (*initial size of the stack*)
   mutable proc_is_fun : bool; (*is it a function?*)
}
A procedure.

type program = {
   mutable prog_source_name : string; (*filename of the source code*)
   prog_procs : procedure list; (*procedures of the program (must be a prefix in-depth "parcours" of the tree)*)
   prog_max_depth : int; (*maximal lexical depth*)
}
A program.

type meta_instr =
| If of (variable * base_block * base_block * base_block) (*a if ... then ... else ... construction*)
| While of (variable * base_block * base_block * base_block) (*a while do ... done construction (the first base block is here to compute the condition)*)
| End
A meta instruction (an instruction which has several base blocks as argument).

type instr =
| Add_i of (variable * variable * variable) (*x1 <- x2 + x3 where the xi are integers*)
| And of (variable * variable * variable) (*x1 <- x2 && x3*)
| Cmp_i of (variable * variable * flag * variable) (*compare x2 and x3 where the xi are integers and put the result in x1*)
| Delete of variable (*free the memory used by a variable*)
| Div_i of (variable * variable * variable) (*x1 <- x2 / x3 where the xi are integers*)
| Mod_i of (variable * variable * variable) (*x1 <- x2 mod x3 where the xi are integers*)
| Mov_i of (variable * variable) (*x1 <- x2 where the xi are integers*)
| Mov_b of (variable * variable) (*x1 <- x2 where the xi are booleans*)
| Mult_i of (variable * variable * variable) (*x1 <- x2 * x3 where the xi are integers*)
| Neg_i of (variable * variable) (*x1 <- -x2*)
| New of (variable * int) (*allocate a value of which size is specified in bytes*)
| Not of (variable * variable) (*x1 <- not x2*)
| Or of (variable * variable * variable) (*x1 <- x2 && x3*)
| Sub_i of (variable * variable * variable) (*x1 <- x2 - x3*)
| Fun of (variable * procedure * variable list) (*x <- f(args)*)
| Return of variable (*return a value (for functions)*)
| Proc of (procedure * variable list) (*a procedure call*)
| Nop
| Read_flag of (flag * variable) (*set a variable's contents according to a flag*)
| Address_of of (variable * variable) (*x1 <- &x2*)
| Spill_var of variable
| Assert_avail of variable (*make sure the variable is available in a register after this instuction*)
| Check_avail of variable (*we are going to use this variable, make sure that everything is going to be ok*)
| Check_avail_with_flags of variable (*like Check_avail but the variable might be stored in flags*)
| Call of string (*a call*)
| Push of variable (*push a variable on the top of the stack*)
| Push_o of (variable * int) (*push n bytes on the stack*)
| Spill of (bool * register * variable_def) (*spill a variable (store it on the stack); the first argument should be set to true iff we are not in the same lexical scope as the variable*)
| Unspill of (bool * variable) (*unspill a variable (cf. Spill for the first argument)*)
| Spill_all (*spill all variables still in a register*)
| Set_var of (flag * variable) (*set a register to 0 or 1 according to some flags*)
| Code of string (*some verbatim code (should only be used for debugging purposes)*)
An assembly instruction.

type base_block = {
   mutable bb_block : instr list;
   mutable bb_link : meta_instr;
}
A base block.
val new_base_block : meta_instr -> base_block
Create a new base block.
val proc_stub : string -> variable_def list -> int -> procedure
Create a stub for a procedure, given its name, arguments and lexical depth.
val is_constant : variable -> bool
Is a variable a constant?
val commute_instr : instr -> instr
Use commutativity on an instruction.