Minor modifications, adding comments
This commit is contained in:
@ -58,7 +58,8 @@ let () =
|
|||||||
| Lexer.LexingError msg ->
|
| Lexer.LexingError msg ->
|
||||||
Printf.fprintf stderr "%a: %s\n" print_position lexbuf msg;
|
Printf.fprintf stderr "%a: %s\n" print_position lexbuf msg;
|
||||||
exit (-1)
|
exit (-1)
|
||||||
| Parser.Error -> Printf.fprintf stderr "%a: syntax error\n" print_position lexbuf;
|
| Parser.Error ->
|
||||||
|
Printf.fprintf stderr "%a: syntax error\n" print_position lexbuf;
|
||||||
exit (-1)
|
exit (-1)
|
||||||
in
|
in
|
||||||
let _ =
|
let _ =
|
||||||
|
|||||||
@ -5,7 +5,7 @@ open Lexing
|
|||||||
(* Command Arguments *)
|
(* Command Arguments *)
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
Clap.description "Interpreter for MiniImp language.";
|
Clap.description "Interpreter for MiniImp language to RISC code.";
|
||||||
|
|
||||||
let files = Clap.section ~description: "Files to consider." "FILES" in
|
let files = Clap.section ~description: "Files to consider." "FILES" in
|
||||||
let values = Clap.section ~description: "Input values." "VALUES" in
|
let values = Clap.section ~description: "Input values." "VALUES" in
|
||||||
@ -36,6 +36,22 @@ let () =
|
|||||||
false
|
false
|
||||||
in
|
in
|
||||||
|
|
||||||
|
let checkundefined = Clap.flag
|
||||||
|
~description: "Optional flag for disabling the check for undefined variables."
|
||||||
|
~section: values
|
||||||
|
~unset_long: "undefined"
|
||||||
|
~unset_short: 'u'
|
||||||
|
true
|
||||||
|
in
|
||||||
|
|
||||||
|
let optimizereg = Clap.flag
|
||||||
|
~description: "Optional flag for disabling optimizing registers with liveness analysis."
|
||||||
|
~section: values
|
||||||
|
~unset_long: "liveness"
|
||||||
|
~unset_short: 'l'
|
||||||
|
true
|
||||||
|
in
|
||||||
|
|
||||||
let inputval = Clap.default_int
|
let inputval = Clap.default_int
|
||||||
~description: "Optional input value to feed to the program. \
|
~description: "Optional input value to feed to the program. \
|
||||||
If not specified it is read from stdin."
|
If not specified it is read from stdin."
|
||||||
@ -85,7 +101,7 @@ let () =
|
|||||||
CfgRISC.convert
|
CfgRISC.convert
|
||||||
in
|
in
|
||||||
|
|
||||||
let () = (
|
if checkundefined then (
|
||||||
match DefinedVariables.compute_defined_variables return_value |>
|
match DefinedVariables.compute_defined_variables return_value |>
|
||||||
DefinedVariables.check_undefined_variables
|
DefinedVariables.check_undefined_variables
|
||||||
with
|
with
|
||||||
@ -94,13 +110,20 @@ let () =
|
|||||||
Printf.printf "Error: undefined variables: %a\n"
|
Printf.printf "Error: undefined variables: %a\n"
|
||||||
DefinedVariables.Variable.pplist l;
|
DefinedVariables.Variable.pplist l;
|
||||||
exit (-1)
|
exit (-1)
|
||||||
) in
|
) else ();
|
||||||
|
|
||||||
|
let return_value =
|
||||||
|
if optimizereg then
|
||||||
|
return_value |>
|
||||||
|
LiveVariables.compute_live_variables |>
|
||||||
|
LiveVariables.optimize_cfg |>
|
||||||
|
LiveVariables.compute_cfg
|
||||||
|
else
|
||||||
|
return_value
|
||||||
|
in
|
||||||
|
|
||||||
let return_value =
|
let return_value =
|
||||||
return_value |>
|
return_value |>
|
||||||
LiveVariables.compute_live_variables |>
|
|
||||||
LiveVariables.optimize_cfg |>
|
|
||||||
LiveVariables.compute_cfg |>
|
|
||||||
ReduceRegisters.reduceregisters registers |>
|
ReduceRegisters.reduceregisters registers |>
|
||||||
RISC.convert
|
RISC.convert
|
||||||
in
|
in
|
||||||
|
|||||||
@ -41,7 +41,9 @@ module Make (M: Cfg.PrintableType) (I: Cfg.PrintableType) = struct
|
|||||||
match Utility.equality a.internalin b.internalin,
|
match Utility.equality a.internalin b.internalin,
|
||||||
Utility.equality a.internalout b.internalout,
|
Utility.equality a.internalout b.internalout,
|
||||||
(List.fold_left2 (fun acc (ain, aout) (bin, bout)
|
(List.fold_left2 (fun acc (ain, aout) (bin, bout)
|
||||||
-> acc && (Utility.equality ain bin) && (Utility.equality aout bout)
|
-> acc &&
|
||||||
|
(Utility.equality ain bin) &&
|
||||||
|
(Utility.equality aout bout)
|
||||||
) true a.internalbetween b.internalbetween)
|
) true a.internalbetween b.internalbetween)
|
||||||
with
|
with
|
||||||
| true, true, true -> true
|
| true, true, true -> true
|
||||||
@ -54,7 +56,7 @@ module Make (M: Cfg.PrintableType) (I: Cfg.PrintableType) = struct
|
|||||||
internalvar: internalnode Cfg.NodeMap.t;
|
internalvar: internalnode Cfg.NodeMap.t;
|
||||||
}
|
}
|
||||||
|
|
||||||
let compareinternal (a: internalnode Cfg.NodeMap.t) (b: internalnode Cfg.NodeMap.t) =
|
let compareinternal a b =
|
||||||
Cfg.NodeMap.fold
|
Cfg.NodeMap.fold
|
||||||
(fun node bi acc ->
|
(fun node bi acc ->
|
||||||
match Cfg.NodeMap.find_opt node a with
|
match Cfg.NodeMap.find_opt node a with
|
||||||
@ -141,7 +143,9 @@ module Make (M: Cfg.PrintableType) (I: Cfg.PrintableType) = struct
|
|||||||
|
|
||||||
let fixed_point
|
let fixed_point
|
||||||
?(init : (elt list -> internalnode) =
|
?(init : (elt list -> internalnode) =
|
||||||
(fun _ -> {internalin = []; internalout = []; internalbetween = []}))
|
(fun _ -> {internalin = [];
|
||||||
|
internalout = [];
|
||||||
|
internalbetween = []}))
|
||||||
?(update : (t -> Cfg.Node.t -> internalnode) =
|
?(update : (t -> Cfg.Node.t -> internalnode) =
|
||||||
(fun t n -> Cfg.NodeMap.find n t.internalvar))
|
(fun t n -> Cfg.NodeMap.find n t.internalvar))
|
||||||
(t: t)
|
(t: t)
|
||||||
@ -150,7 +154,7 @@ module Make (M: Cfg.PrintableType) (I: Cfg.PrintableType) = struct
|
|||||||
the update function takes the node and the whole structure and is
|
the update function takes the node and the whole structure and is
|
||||||
expected to return the updated structure for the appropriate node,
|
expected to return the updated structure for the appropriate node,
|
||||||
update function is applied to the resulting structure until no change is
|
update function is applied to the resulting structure until no change is
|
||||||
observed
|
observed with compareinternal function
|
||||||
*)
|
*)
|
||||||
let rec helper t =
|
let rec helper t =
|
||||||
let newt =
|
let newt =
|
||||||
|
|||||||
@ -18,7 +18,9 @@ module type C = sig
|
|||||||
val from_cfg : cfgt -> t
|
val from_cfg : cfgt -> t
|
||||||
val to_cfg : t -> cfgt
|
val to_cfg : t -> cfgt
|
||||||
|
|
||||||
val fixed_point : ?init:(elt list -> internalnode) -> ?update:(t -> Cfg.Node.t -> internalnode) -> t -> t
|
val fixed_point :
|
||||||
|
?init:(elt list -> internalnode) ->
|
||||||
|
?update:(t -> Cfg.Node.t -> internalnode) -> t -> t
|
||||||
|
|
||||||
val pp : out_channel -> t -> unit
|
val pp : out_channel -> t -> unit
|
||||||
end
|
end
|
||||||
|
|||||||
@ -81,6 +81,7 @@ rule read = parse
|
|||||||
(lexbuf.Lexing.lex_curr_p.Lexing.pos_lnum)
|
(lexbuf.Lexing.lex_curr_p.Lexing.pos_lnum)
|
||||||
(lexbuf.Lexing.lex_curr_p.Lexing.pos_lnum)
|
(lexbuf.Lexing.lex_curr_p.Lexing.pos_lnum)
|
||||||
))}
|
))}
|
||||||
|
|
||||||
and comments level = parse
|
and comments level = parse
|
||||||
| "*)" {if level = 0
|
| "*)" {if level = 0
|
||||||
then read lexbuf
|
then read lexbuf
|
||||||
|
|||||||
@ -24,7 +24,6 @@
|
|||||||
%start prg
|
%start prg
|
||||||
|
|
||||||
(* associativity in order of precedence *)
|
(* associativity in order of precedence *)
|
||||||
/*%right rightlowest */
|
|
||||||
%left lowest
|
%left lowest
|
||||||
%right TYPEFUNCTION
|
%right TYPEFUNCTION
|
||||||
%left COMMA
|
%left COMMA
|
||||||
@ -35,7 +34,7 @@
|
|||||||
%left CMP CMPLESS CMPLESSEQ CMPGREATER CMPGREATEREQ
|
%left CMP CMPLESS CMPLESSEQ CMPGREATER CMPGREATEREQ
|
||||||
%left PLUS MINUS
|
%left PLUS MINUS
|
||||||
%left TIMES DIVISION MODULO
|
%left TIMES DIVISION MODULO
|
||||||
%left POWER
|
%right POWER
|
||||||
%right BNOT RAND
|
%right BNOT RAND
|
||||||
%left FIRST SECOND
|
%left FIRST SECOND
|
||||||
%left LAMBDA
|
%left LAMBDA
|
||||||
|
|||||||
@ -25,7 +25,6 @@ module SimpleStatements = struct
|
|||||||
| SimpleDivision of simpleArithmetic * simpleArithmetic
|
| SimpleDivision of simpleArithmetic * simpleArithmetic
|
||||||
| SimpleModulo of simpleArithmetic * simpleArithmetic
|
| SimpleModulo of simpleArithmetic * simpleArithmetic
|
||||||
| SimplePower of simpleArithmetic * simpleArithmetic
|
| SimplePower of simpleArithmetic * simpleArithmetic
|
||||||
| SimplePowerMod of simpleArithmetic * simpleArithmetic * simpleArithmetic
|
|
||||||
| SimpleRand of simpleArithmetic
|
| SimpleRand of simpleArithmetic
|
||||||
|
|
||||||
let pp (ppf: out_channel) (c: t) : unit =
|
let pp (ppf: out_channel) (c: t) : unit =
|
||||||
@ -55,7 +54,6 @@ module SimpleStatements = struct
|
|||||||
| SimpleDivision (a1, a2) -> Printf.fprintf ppf "{%a / %a}" helper_a a1 helper_a a2
|
| SimpleDivision (a1, a2) -> Printf.fprintf ppf "{%a / %a}" helper_a a1 helper_a a2
|
||||||
| SimpleModulo (a1, a2) -> Printf.fprintf ppf "{%a %% %a}" helper_a a1 helper_a a2
|
| SimpleModulo (a1, a2) -> Printf.fprintf ppf "{%a %% %a}" helper_a a1 helper_a a2
|
||||||
| SimplePower (a1, a2) -> Printf.fprintf ppf "{%a ^ %a}" helper_a a1 helper_a a2
|
| SimplePower (a1, a2) -> Printf.fprintf ppf "{%a ^ %a}" helper_a a1 helper_a a2
|
||||||
| SimplePowerMod (a1, a2, a3) -> Printf.fprintf ppf "{powmod %a %a %a}" helper_a a1 helper_a a2 helper_a a3
|
|
||||||
| SimpleRand (a) -> Printf.fprintf ppf "{rand %a}" helper_a a
|
| SimpleRand (a) -> Printf.fprintf ppf "{rand %a}" helper_a a
|
||||||
in
|
in
|
||||||
helper_c ppf c
|
helper_c ppf c
|
||||||
@ -69,18 +67,19 @@ module SSCfg = Cfg.Make(SimpleStatements)
|
|||||||
let rec convert_c (prevcfg: SSCfg.t) (prg: Types.c_exp) : SSCfg.t =
|
let rec convert_c (prevcfg: SSCfg.t) (prg: Types.c_exp) : SSCfg.t =
|
||||||
let open SimpleStatements in
|
let open SimpleStatements in
|
||||||
match prg with
|
match prg with
|
||||||
| Skip ->
|
| Skip -> (* we preserve the skips *)
|
||||||
prevcfg |> SSCfg.addToLastNode SimpleSkip
|
prevcfg |> SSCfg.addToLastNode SimpleSkip
|
||||||
|
|
||||||
| Assignment (x, a) ->
|
| Assignment (x, a) -> (* we simply add the assignment to the terminal node *)
|
||||||
prevcfg |> SSCfg.addToLastNode (SimpleAssignment (x, convert_a a))
|
prevcfg |> SSCfg.addToLastNode (SimpleAssignment (x, convert_a a))
|
||||||
|
|
||||||
| Sequence (c1, c2) ->
|
| Sequence (c1, c2) -> (* we first convert the first sequence, then the second
|
||||||
|
using the previous as prevcfg *)
|
||||||
let cfg1 = convert_c prevcfg c1 in
|
let cfg1 = convert_c prevcfg c1 in
|
||||||
let cfg2 = convert_c cfg1 c2 in
|
let cfg2 = convert_c cfg1 c2 in
|
||||||
cfg2
|
cfg2
|
||||||
|
|
||||||
| If (b, c1, c2) ->
|
| If (b, c1, c2) -> (* constructs two branches with a two new nodes *)
|
||||||
let convertedb = convert_b b in
|
let convertedb = convert_b b in
|
||||||
let cfg1 = convert_c SSCfg.empty c1 in
|
let cfg1 = convert_c SSCfg.empty c1 in
|
||||||
let cfg2 = convert_c SSCfg.empty c2 in
|
let cfg2 = convert_c SSCfg.empty c2 in
|
||||||
@ -93,7 +92,7 @@ let rec convert_c (prevcfg: SSCfg.t) (prg: Types.c_exp) : SSCfg.t =
|
|||||||
NodeMap.add_to_list entrynode (SimpleGuard convertedb) |>
|
NodeMap.add_to_list entrynode (SimpleGuard convertedb) |>
|
||||||
NodeMap.add_to_list exitnode (SimpleSkip) }
|
NodeMap.add_to_list exitnode (SimpleSkip) }
|
||||||
|
|
||||||
| While (b, c) ->
|
| While (b, c) -> (* constructs a loop, needs three new nodes *)
|
||||||
let convertedb = convert_b b in
|
let convertedb = convert_b b in
|
||||||
let cfg = convert_c SSCfg.empty c in
|
let cfg = convert_c SSCfg.empty c in
|
||||||
let cfginitial = Option.get cfg.initial in
|
let cfginitial = Option.get cfg.initial in
|
||||||
@ -124,7 +123,8 @@ let rec convert_c (prevcfg: SSCfg.t) (prg: Types.c_exp) : SSCfg.t =
|
|||||||
NodeMap.add_to_list exitnode (SimpleSkip)
|
NodeMap.add_to_list exitnode (SimpleSkip)
|
||||||
} |> SSCfg.concat prevcfg
|
} |> SSCfg.concat prevcfg
|
||||||
|
|
||||||
| For (assignment, guard, increment, body) ->
|
| For (assignment, guard, increment, body) -> (* constructs a loop, needs
|
||||||
|
two new nodes *)
|
||||||
let cfgassignment = convert_c SSCfg.empty assignment in
|
let cfgassignment = convert_c SSCfg.empty assignment in
|
||||||
let convertedguard = convert_b guard in
|
let convertedguard = convert_b guard in
|
||||||
let cfgincrement = convert_c SSCfg.empty increment in
|
let cfgincrement = convert_c SSCfg.empty increment in
|
||||||
|
|||||||
@ -24,7 +24,6 @@ module SimpleStatements : sig
|
|||||||
| SimpleDivision of simpleArithmetic * simpleArithmetic
|
| SimpleDivision of simpleArithmetic * simpleArithmetic
|
||||||
| SimpleModulo of simpleArithmetic * simpleArithmetic
|
| SimpleModulo of simpleArithmetic * simpleArithmetic
|
||||||
| SimplePower of simpleArithmetic * simpleArithmetic
|
| SimplePower of simpleArithmetic * simpleArithmetic
|
||||||
| SimplePowerMod of simpleArithmetic * simpleArithmetic * simpleArithmetic
|
|
||||||
| SimpleRand of simpleArithmetic
|
| SimpleRand of simpleArithmetic
|
||||||
|
|
||||||
val pp : out_channel -> t -> unit
|
val pp : out_channel -> t -> unit
|
||||||
|
|||||||
@ -706,9 +706,6 @@ and c_ss_sa
|
|||||||
(convertedcode @ [BRegOp (Pow, partialresreg1, partialresreg2, register)], m)
|
(convertedcode @ [BRegOp (Pow, partialresreg1, partialresreg2, register)], m)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
| SimplePowerMod (_a1, _a2, _a3) -> (
|
|
||||||
failwith "not implemented"
|
|
||||||
)
|
|
||||||
| SimpleRand (a) -> (
|
| SimpleRand (a) -> (
|
||||||
let partialresreg, m, _partialresvar = RegisterMap.get_fresh_register m in
|
let partialresreg, m, _partialresvar = RegisterMap.get_fresh_register m in
|
||||||
let convertedcode, m = c_ss_sa a m convertedcode partialresreg in
|
let convertedcode, m = c_ss_sa a m convertedcode partialresreg in
|
||||||
|
|||||||
@ -32,7 +32,7 @@
|
|||||||
%left DIVISION
|
%left DIVISION
|
||||||
%left MODULO
|
%left MODULO
|
||||||
%left TIMES
|
%left TIMES
|
||||||
%left POWER
|
%right POWER
|
||||||
%left DO
|
%left DO
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|||||||
@ -19,6 +19,8 @@ module RISCArchitecture = struct
|
|||||||
end
|
end
|
||||||
|
|
||||||
let convert (prg: RISC.RISCAssembly.t) : RISC.RISCAssembly.risci list CodeMap.t =
|
let convert (prg: RISC.RISCAssembly.t) : RISC.RISCAssembly.risci list CodeMap.t =
|
||||||
|
(* takes as input a sequence of RISC commands and computes a map to the right
|
||||||
|
labels for easier execution *)
|
||||||
let rec helper
|
let rec helper
|
||||||
(prg: RISC.RISCAssembly.risci list)
|
(prg: RISC.RISCAssembly.risci list)
|
||||||
(current: RISC.RISCAssembly.risci list)
|
(current: RISC.RISCAssembly.risci list)
|
||||||
@ -98,7 +100,8 @@ let reduce_instructions (prg: RISCArchitecture.t) (lo: string list) : int =
|
|||||||
None -> prg (* should never happen *)
|
None -> prg (* should never happen *)
|
||||||
| Some i ->
|
| Some i ->
|
||||||
if i + 1 < (List.length lo) then
|
if i + 1 < (List.length lo) then
|
||||||
helper prg (CodeMap.find (List.nth lo (i+1)) prg.code) (List.nth lo (i+1))
|
helper
|
||||||
|
prg (CodeMap.find (List.nth lo (i+1)) prg.code) (List.nth lo (i+1))
|
||||||
else
|
else
|
||||||
prg
|
prg
|
||||||
)
|
)
|
||||||
@ -109,32 +112,45 @@ let reduce_instructions (prg: RISCArchitecture.t) (lo: string list) : int =
|
|||||||
(RegisterMap.find {index = r1.index} prg.registers)
|
(RegisterMap.find {index = r1.index} prg.registers)
|
||||||
(RegisterMap.find {index = r2.index} prg.registers)
|
(RegisterMap.find {index = r2.index} prg.registers)
|
||||||
in
|
in
|
||||||
helper {prg with registers = RegisterMap.add {index = r3.index} n prg.registers} tl current_label
|
helper { prg with
|
||||||
|
registers = RegisterMap.add {index = r3.index} n prg.registers }
|
||||||
|
tl current_label
|
||||||
)
|
)
|
||||||
| BImmOp (biop, r1, i, r3) :: tl -> (
|
| BImmOp (biop, r1, i, r3) :: tl -> (
|
||||||
let n = (match_operator_i biop)
|
let n = (match_operator_i biop)
|
||||||
(RegisterMap.find {index = r1.index} prg.registers)
|
(RegisterMap.find {index = r1.index} prg.registers)
|
||||||
i
|
i
|
||||||
in
|
in
|
||||||
helper {prg with registers = RegisterMap.add {index = r3.index} n prg.registers} tl current_label
|
helper { prg with
|
||||||
|
registers = RegisterMap.add {index = r3.index} n prg.registers }
|
||||||
|
tl current_label
|
||||||
)
|
)
|
||||||
| URegOp (urop, r1, r3) :: tl -> (
|
| URegOp (urop, r1, r3) :: tl -> (
|
||||||
match urop with
|
match urop with
|
||||||
| Copy -> (
|
| Copy -> (
|
||||||
let n = RegisterMap.find {index = r1.index} prg.registers in
|
let n = RegisterMap.find {index = r1.index} prg.registers in
|
||||||
helper {prg with registers = RegisterMap.add {index = r3.index} n prg.registers} tl current_label
|
helper { prg with
|
||||||
|
registers =
|
||||||
|
RegisterMap.add {index = r3.index} n prg.registers }
|
||||||
|
tl current_label
|
||||||
)
|
)
|
||||||
| Not -> (
|
| Not -> (
|
||||||
let n = Utility.int_not
|
let n = Utility.int_not
|
||||||
(RegisterMap.find {index = r1.index} prg.registers)
|
(RegisterMap.find {index = r1.index} prg.registers)
|
||||||
in
|
in
|
||||||
helper {prg with registers = RegisterMap.add {index = r3.index} n prg.registers} tl current_label
|
helper { prg with
|
||||||
|
registers =
|
||||||
|
RegisterMap.add {index = r3.index} n prg.registers }
|
||||||
|
tl current_label
|
||||||
)
|
)
|
||||||
| Rand -> (
|
| Rand -> (
|
||||||
let n = Random.int
|
let n = Random.int
|
||||||
(RegisterMap.find {index = r1.index} prg.registers)
|
(RegisterMap.find {index = r1.index} prg.registers)
|
||||||
in
|
in
|
||||||
helper {prg with registers = RegisterMap.add {index = r3.index} n prg.registers} tl current_label
|
helper { prg with
|
||||||
|
registers =
|
||||||
|
RegisterMap.add {index = r3.index} n prg.registers }
|
||||||
|
tl current_label
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
| Load (r1, r3) :: tl -> (
|
| Load (r1, r3) :: tl -> (
|
||||||
@ -143,12 +159,16 @@ let reduce_instructions (prg: RISCArchitecture.t) (lo: string list) : int =
|
|||||||
(RegisterMap.find {index = r1.index} prg.registers)
|
(RegisterMap.find {index = r1.index} prg.registers)
|
||||||
prg.memory
|
prg.memory
|
||||||
in
|
in
|
||||||
helper {prg with registers = RegisterMap.add {index = r3.index} n prg.registers} tl current_label
|
helper { prg with
|
||||||
|
registers = RegisterMap.add {index = r3.index} n prg.registers }
|
||||||
|
tl current_label
|
||||||
)
|
)
|
||||||
| LoadI (i, r3) :: tl -> (
|
| LoadI (i, r3) :: tl -> (
|
||||||
let n = i
|
let n = i
|
||||||
in
|
in
|
||||||
helper {prg with registers = RegisterMap.add {index = r3.index} n prg.registers} tl current_label
|
helper { prg with
|
||||||
|
registers = RegisterMap.add {index = r3.index} n prg.registers }
|
||||||
|
tl current_label
|
||||||
)
|
)
|
||||||
| Store (r1, r3) :: tl -> (
|
| Store (r1, r3) :: tl -> (
|
||||||
let n = RegisterMap.find {index = r1.index} prg.registers in
|
let n = RegisterMap.find {index = r1.index} prg.registers in
|
||||||
@ -166,12 +186,17 @@ let reduce_instructions (prg: RISCArchitecture.t) (lo: string list) : int =
|
|||||||
)
|
)
|
||||||
| Label _ :: tl -> helper prg tl current_label
|
| Label _ :: tl -> helper prg tl current_label
|
||||||
in
|
in
|
||||||
RegisterMap.find
|
match
|
||||||
prg.outputreg
|
RegisterMap.find_opt
|
||||||
(helper prg (CodeMap.find "main" prg.code) "main").registers
|
prg.outputreg
|
||||||
|
(helper prg (CodeMap.find "main" prg.code) "main").registers
|
||||||
|
with
|
||||||
|
Some x -> x
|
||||||
|
| None -> failwith "Output register not found"
|
||||||
|
|
||||||
|
|
||||||
let reduce (prg: RISC.RISCAssembly.t) : int =
|
let reduce (prg: RISC.RISCAssembly.t) : int =
|
||||||
|
(* takes assembly and execute it *)
|
||||||
reduce_instructions
|
reduce_instructions
|
||||||
{code = convert prg;
|
{code = convert prg;
|
||||||
registers = (
|
registers = (
|
||||||
|
|||||||
@ -191,6 +191,7 @@ let update (t: DVCfg.t) (node: Cfg.Node.t) : DVCfg.internalnode =
|
|||||||
|
|
||||||
|
|
||||||
let compute_defined_variables (cfg: RISCCfg.t) : DVCfg.t =
|
let compute_defined_variables (cfg: RISCCfg.t) : DVCfg.t =
|
||||||
|
(* creates the DVCfg structure and finds the fixed point *)
|
||||||
let all_variables = List.fold_left
|
let all_variables = List.fold_left
|
||||||
(fun acc (_, code) ->
|
(fun acc (_, code) ->
|
||||||
Utility.unique_union acc (variables_all code))
|
Utility.unique_union acc (variables_all code))
|
||||||
@ -208,6 +209,7 @@ let compute_defined_variables (cfg: RISCCfg.t) : DVCfg.t =
|
|||||||
|
|
||||||
|
|
||||||
let check_undefined_variables (dvcfg: DVCfg.t) : Variable.t list option =
|
let check_undefined_variables (dvcfg: DVCfg.t) : Variable.t list option =
|
||||||
|
(* returns all undefined variables previously computed *)
|
||||||
let helper (node: Cfg.Node.t) (dvcfg: DVCfg.t) : Variable.t list option =
|
let helper (node: Cfg.Node.t) (dvcfg: DVCfg.t) : Variable.t list option =
|
||||||
let code = match Cfg.NodeMap.find_opt node dvcfg.t.content with
|
let code = match Cfg.NodeMap.find_opt node dvcfg.t.content with
|
||||||
None -> []
|
None -> []
|
||||||
@ -257,4 +259,5 @@ let check_undefined_variables (dvcfg: DVCfg.t) : Variable.t list option =
|
|||||||
|
|
||||||
|
|
||||||
let compute_cfg (dvcfg: DVCfg.t) : RISCCfg.t =
|
let compute_cfg (dvcfg: DVCfg.t) : RISCCfg.t =
|
||||||
|
(* no change to the cfg so returned as is *)
|
||||||
DVCfg.to_cfg dvcfg
|
DVCfg.to_cfg dvcfg
|
||||||
|
|||||||
@ -238,14 +238,14 @@ let optimize_cfg (t: DVCfg.t) : DVCfg.t =
|
|||||||
(newassignments, newt)
|
(newassignments, newt)
|
||||||
in
|
in
|
||||||
|
|
||||||
(* --------- *)
|
(* ------------------- *)
|
||||||
|
|
||||||
let assignments = VariableMap.empty in
|
let assignments = VariableMap.empty in
|
||||||
|
|
||||||
let a, newt =
|
let a, newt =
|
||||||
Cfg.NodeSet.fold (* for each node we replace all the variables with the
|
Cfg.NodeSet.fold (* for each node we replace all the variables with the
|
||||||
optimized ones *)
|
optimized ones *)
|
||||||
(fun node (ass, t) -> aux ass t node)
|
(fun node (assign, t) -> aux assign t node)
|
||||||
t.t.nodes
|
t.t.nodes
|
||||||
(assignments, t)
|
(assignments, t)
|
||||||
in
|
in
|
||||||
|
|||||||
@ -18,7 +18,8 @@ module RISCCfg = CfgRISC.RISCCfg
|
|||||||
module VariableMap = Map.Make(Variable)
|
module VariableMap = Map.Make(Variable)
|
||||||
|
|
||||||
let variables_frequency (instr : RISCCfg.elt) : (Variable.t * int) list =
|
let variables_frequency (instr : RISCCfg.elt) : (Variable.t * int) list =
|
||||||
let add_one = (fun x -> match x with None -> Some 1 | Some x -> Some (x + 1)) in
|
let add_one = (fun x -> match x with None -> Some 1 | Some x -> Some (x + 1))
|
||||||
|
in
|
||||||
|
|
||||||
let helper (acc: int VariableMap.t) (instr: RISCCfg.elt) : int VariableMap.t =
|
let helper (acc: int VariableMap.t) (instr: RISCCfg.elt) : int VariableMap.t =
|
||||||
match instr with
|
match instr with
|
||||||
@ -40,7 +41,9 @@ let variables_frequency (instr : RISCCfg.elt) : (Variable.t * int) list =
|
|||||||
|
|
||||||
helper VariableMap.empty instr |> VariableMap.to_list
|
helper VariableMap.empty instr |> VariableMap.to_list
|
||||||
|
|
||||||
let variables_all_frequency (instructions : RISCCfg.elt list) : (Variable.t * int) list =
|
(* computes syntactic frequency of all variables in the code *)
|
||||||
|
let variables_all_frequency (instructions : RISCCfg.elt list)
|
||||||
|
: (Variable.t * int) list =
|
||||||
List.fold_left
|
List.fold_left
|
||||||
( fun (acc: int VariableMap.t) (instr: RISCCfg.elt) ->
|
( fun (acc: int VariableMap.t) (instr: RISCCfg.elt) ->
|
||||||
VariableMap.union
|
VariableMap.union
|
||||||
@ -50,16 +53,20 @@ let variables_all_frequency (instructions : RISCCfg.elt list) : (Variable.t * in
|
|||||||
|
|
||||||
|
|
||||||
let reduceregisters (n: int) (cfg: RISCCfg.t) : RISCCfg.t =
|
let reduceregisters (n: int) (cfg: RISCCfg.t) : RISCCfg.t =
|
||||||
(if n < 4 then (failwith "ReduceRegisters: number of registers too small") else ());
|
(if n < 4 then (
|
||||||
|
failwith "ReduceRegisters: number of registers too small"
|
||||||
|
) else ());
|
||||||
|
|
||||||
(* we get all the variables with associated frequency (only syntactic use) *)
|
(* we get all the variables with associated frequency (only syntactic use) *)
|
||||||
let all_variables = List.fold_left
|
let all_variables = List.fold_left
|
||||||
(fun acc (_, code) ->
|
(fun acc (_, code) ->
|
||||||
Utility.unique_union_assoc (fun _n x y -> x + y) acc (variables_all_frequency code))
|
Utility.unique_union_assoc
|
||||||
|
(fun _n x y -> x + y) acc (variables_all_frequency code))
|
||||||
[]
|
[]
|
||||||
(Cfg.NodeMap.to_list cfg.content)
|
(Cfg.NodeMap.to_list cfg.content)
|
||||||
in
|
in
|
||||||
|
|
||||||
|
(* add one to in and out variables *)
|
||||||
let all_variables =
|
let all_variables =
|
||||||
match cfg.inputOutputVar with
|
match cfg.inputOutputVar with
|
||||||
| None -> all_variables
|
| None -> all_variables
|
||||||
@ -80,6 +87,8 @@ let reduceregisters (n: int) (cfg: RISCCfg.t) : RISCCfg.t =
|
|||||||
)
|
)
|
||||||
in
|
in
|
||||||
|
|
||||||
|
(* replace each operation with a list of operations that have the new
|
||||||
|
registers or load from memory *)
|
||||||
let replaceregisters
|
let replaceregisters
|
||||||
(remappedregisters: Variable.t VariableMap.t)
|
(remappedregisters: Variable.t VariableMap.t)
|
||||||
(memorymap: int VariableMap.t)
|
(memorymap: int VariableMap.t)
|
||||||
@ -143,7 +152,10 @@ let reduceregisters (n: int) (cfg: RISCCfg.t) : RISCCfg.t =
|
|||||||
BRegOp (brop, tmpreg1, tmpreg2, tmpreg2);
|
BRegOp (brop, tmpreg1, tmpreg2, tmpreg2);
|
||||||
LoadI (m3, tmpreg1);
|
LoadI (m3, tmpreg1);
|
||||||
Store (tmpreg2, tmpreg1)]
|
Store (tmpreg2, tmpreg1)]
|
||||||
| _ -> [BRegOp (brop, {index = r1.index}, {index = r2.index}, {index = r3.index})]
|
| _ -> [BRegOp (brop,
|
||||||
|
{index = r1.index},
|
||||||
|
{index = r2.index},
|
||||||
|
{index = r3.index})]
|
||||||
)
|
)
|
||||||
| BImmOp (biop, r1, i, r3) -> (
|
| BImmOp (biop, r1, i, r3) -> (
|
||||||
match ( VariableMap.find_opt r1.index remappedregisters,
|
match ( VariableMap.find_opt r1.index remappedregisters,
|
||||||
@ -237,8 +249,8 @@ let reduceregisters (n: int) (cfg: RISCCfg.t) : RISCCfg.t =
|
|||||||
" registers have no binding.")
|
" registers have no binding.")
|
||||||
)
|
)
|
||||||
| Store (r1, r3) -> (
|
| Store (r1, r3) -> (
|
||||||
(* we want to maybe store an address in memory (very confusing, don't
|
(* we want to maybe store an address in memory (very confusing,
|
||||||
think can happen) *)
|
but maybe possible) *)
|
||||||
match ( VariableMap.find_opt r1.index remappedregisters,
|
match ( VariableMap.find_opt r1.index remappedregisters,
|
||||||
VariableMap.find_opt r3.index remappedregisters,
|
VariableMap.find_opt r3.index remappedregisters,
|
||||||
VariableMap.find_opt r1.index memorymap,
|
VariableMap.find_opt r1.index memorymap,
|
||||||
@ -269,6 +281,8 @@ let reduceregisters (n: int) (cfg: RISCCfg.t) : RISCCfg.t =
|
|||||||
in
|
in
|
||||||
|
|
||||||
|
|
||||||
|
(* partition the variables into two sets, most frequent and least frequent
|
||||||
|
then apply the transformation *)
|
||||||
let aux (cfg: RISCCfg.t) (all_variables: (string * int) list) =
|
let aux (cfg: RISCCfg.t) (all_variables: (string * int) list) =
|
||||||
(* we keep the first two variables free for immediate use *)
|
(* we keep the first two variables free for immediate use *)
|
||||||
let most_frequent, least_frequent =
|
let most_frequent, least_frequent =
|
||||||
@ -298,8 +312,13 @@ let reduceregisters (n: int) (cfg: RISCCfg.t) : RISCCfg.t =
|
|||||||
let newcfg = {
|
let newcfg = {
|
||||||
cfg with
|
cfg with
|
||||||
content = Cfg.NodeMap.map
|
content = Cfg.NodeMap.map
|
||||||
(fun x -> replaceregisters most_frequent_mapping least_frequent_mapping ["1"; "2"] x)
|
( fun x ->
|
||||||
cfg.content}
|
replaceregisters
|
||||||
|
most_frequent_mapping
|
||||||
|
least_frequent_mapping
|
||||||
|
["1"; "2"]
|
||||||
|
x
|
||||||
|
) cfg.content}
|
||||||
in
|
in
|
||||||
|
|
||||||
match newcfg.inputOutputVar with
|
match newcfg.inputOutputVar with
|
||||||
@ -417,7 +436,6 @@ let reduceregisters (n: int) (cfg: RISCCfg.t) : RISCCfg.t =
|
|||||||
)
|
)
|
||||||
in
|
in
|
||||||
|
|
||||||
|
|
||||||
( if List.length all_variables <= n
|
( if List.length all_variables <= n
|
||||||
then cfg
|
then cfg
|
||||||
else aux cfg all_variables )
|
else aux cfg all_variables )
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
let rewrite_instructions (prg: Types.p_exp) : Types.p_exp =
|
let rewrite_instructions (prg: Types.p_exp) : Types.p_exp =
|
||||||
(* function takes a program and replaces all occurrences of powermod with
|
(* function takes a program and replaces all occurrences of powermod with
|
||||||
simpler instructions *)
|
simpler instructions *)
|
||||||
let i, o, prg = (
|
|
||||||
match prg with
|
let Main (i, o, prg) = prg in
|
||||||
| Main (i, o, exp) -> i, o, exp
|
|
||||||
) in
|
|
||||||
|
|
||||||
let rec contains_rewrite (prg: Types.c_exp) : Types.a_exp option =
|
let rec contains_rewrite (prg: Types.c_exp) : Types.a_exp option =
|
||||||
(* if the ast contains powermod anywhere returns the powermod, otherwise
|
(* if the ast contains powermod anywhere returns the powermod, otherwise
|
||||||
|
|||||||
Reference in New Issue
Block a user