2024-12-12 16:37:36 +01:00
|
|
|
open Analysis
|
|
|
|
|
|
2024-12-01 12:55:20 +01:00
|
|
|
let globalCounterLabel = ref 0
|
|
|
|
|
|
|
|
|
|
let nextLabel () : string =
|
|
|
|
|
globalCounterLabel := !globalCounterLabel + 1;
|
|
|
|
|
"l" ^ (string_of_int !globalCounterLabel)
|
|
|
|
|
|
|
|
|
|
module RISCAssembly = struct
|
|
|
|
|
type register = {
|
2024-12-03 17:18:42 +01:00
|
|
|
index : string
|
2024-12-01 12:55:20 +01:00
|
|
|
}
|
|
|
|
|
|
2024-12-03 17:18:42 +01:00
|
|
|
type label = string
|
2024-12-01 12:55:20 +01:00
|
|
|
|
|
|
|
|
type risci =
|
|
|
|
|
| Nop
|
|
|
|
|
| BRegOp of brop * register * register * register
|
|
|
|
|
| BImmOp of biop * register * int * register
|
|
|
|
|
| URegOp of urop * register * register
|
|
|
|
|
| Load of register * register
|
2024-12-16 05:15:33 +01:00
|
|
|
| LoadI of int * register
|
2024-12-01 12:55:20 +01:00
|
|
|
| Store of register * register
|
|
|
|
|
| Jump of label
|
|
|
|
|
| CJump of register * label * label
|
|
|
|
|
| Label of label
|
|
|
|
|
and brop =
|
|
|
|
|
| Add
|
|
|
|
|
| Sub
|
|
|
|
|
| Mult
|
|
|
|
|
| Div
|
|
|
|
|
| Mod
|
|
|
|
|
| Pow
|
|
|
|
|
| And
|
|
|
|
|
| Or
|
|
|
|
|
| Eq
|
|
|
|
|
| Less
|
|
|
|
|
| LessEq
|
|
|
|
|
| More
|
|
|
|
|
| MoreEq
|
|
|
|
|
and biop =
|
|
|
|
|
| AddI
|
|
|
|
|
| SubI
|
|
|
|
|
| MultI
|
|
|
|
|
| DivI
|
|
|
|
|
| ModI
|
|
|
|
|
| PowI
|
|
|
|
|
| AndI
|
|
|
|
|
| OrI
|
|
|
|
|
| EqI
|
|
|
|
|
| LessI
|
|
|
|
|
| LessEqI
|
|
|
|
|
| MoreI
|
|
|
|
|
| MoreEqI
|
|
|
|
|
and urop =
|
|
|
|
|
| Not
|
|
|
|
|
| Copy
|
|
|
|
|
| Rand
|
|
|
|
|
|
2024-12-03 17:18:42 +01:00
|
|
|
type t = {
|
|
|
|
|
code : risci list;
|
2024-12-27 21:11:38 +01:00
|
|
|
inputval: int option;
|
|
|
|
|
inputoutputreg: (register * register) option;
|
2024-12-03 17:18:42 +01:00
|
|
|
}
|
2024-12-01 12:55:20 +01:00
|
|
|
|
2024-12-03 17:18:42 +01:00
|
|
|
let pp_risci (ppf: out_channel) (v: risci) : unit =
|
2024-12-01 12:55:20 +01:00
|
|
|
let rec pp_risci (ppf: out_channel) (v: risci) : unit =
|
|
|
|
|
match v with
|
2025-01-27 01:17:53 +01:00
|
|
|
| Nop ->
|
|
|
|
|
Printf.fprintf ppf "\tNop\n"
|
|
|
|
|
| BRegOp (b, r1, r2, r3) ->
|
|
|
|
|
Printf.fprintf ppf "\t%a r%s r%s => r%s\n"
|
|
|
|
|
pp_brop b r1.index r2.index r3.index
|
|
|
|
|
| BImmOp (b, r1, i, r3) ->
|
|
|
|
|
Printf.fprintf ppf "\t%a r%s %d => r%s\n" pp_biop b r1.index i r3.index
|
|
|
|
|
| URegOp (u, r1, r2) ->
|
|
|
|
|
Printf.fprintf ppf "\t%a r%s => r%s\n" pp_urop u r1.index r2.index
|
|
|
|
|
| Load (r1, r2) ->
|
|
|
|
|
Printf.fprintf ppf "\tLoad r%s => r%s\n" r1.index r2.index
|
|
|
|
|
| LoadI (i, r2) ->
|
|
|
|
|
Printf.fprintf ppf "\tLoadI %d => r%s\n" i r2.index
|
|
|
|
|
| Store (r1, r2) ->
|
|
|
|
|
Printf.fprintf ppf "\tStore r%s => r%s\n" r1.index r2.index
|
|
|
|
|
| Jump (label) ->
|
|
|
|
|
Printf.fprintf ppf "\tJump %s\n" label
|
|
|
|
|
| CJump (r, l1, l2) ->
|
|
|
|
|
Printf.fprintf ppf "\tCJump r%s => %s, %s\n" r.index l1 l2
|
|
|
|
|
| Label (label) ->
|
|
|
|
|
Printf.fprintf ppf "%s:" label
|
2024-12-01 12:55:20 +01:00
|
|
|
and pp_brop (ppf: out_channel) (v: brop) : unit =
|
|
|
|
|
match v with
|
|
|
|
|
Add -> Printf.fprintf ppf "Add"
|
|
|
|
|
| Sub -> Printf.fprintf ppf "Sub"
|
|
|
|
|
| Mult -> Printf.fprintf ppf "Mult"
|
|
|
|
|
| Div -> Printf.fprintf ppf "Div"
|
|
|
|
|
| Mod -> Printf.fprintf ppf "Mod"
|
|
|
|
|
| Pow -> Printf.fprintf ppf "Pow"
|
|
|
|
|
| And -> Printf.fprintf ppf "And"
|
|
|
|
|
| Or -> Printf.fprintf ppf "Or"
|
|
|
|
|
| Eq -> Printf.fprintf ppf "Eq"
|
|
|
|
|
| Less -> Printf.fprintf ppf "Less"
|
|
|
|
|
| LessEq -> Printf.fprintf ppf "LessEq"
|
|
|
|
|
| More -> Printf.fprintf ppf "More"
|
|
|
|
|
| MoreEq -> Printf.fprintf ppf "MoreEq"
|
|
|
|
|
and pp_biop (ppf: out_channel) (v: biop) : unit =
|
|
|
|
|
match v with
|
|
|
|
|
AddI -> Printf.fprintf ppf "AddI"
|
|
|
|
|
| SubI -> Printf.fprintf ppf "SubI"
|
|
|
|
|
| MultI -> Printf.fprintf ppf "MultI"
|
|
|
|
|
| DivI -> Printf.fprintf ppf "DivI"
|
|
|
|
|
| ModI -> Printf.fprintf ppf "ModI"
|
|
|
|
|
| PowI -> Printf.fprintf ppf "PowI"
|
|
|
|
|
| AndI -> Printf.fprintf ppf "AndI"
|
|
|
|
|
| OrI -> Printf.fprintf ppf "OrI"
|
|
|
|
|
| EqI -> Printf.fprintf ppf "EqI"
|
|
|
|
|
| LessI -> Printf.fprintf ppf "LessI"
|
|
|
|
|
| LessEqI -> Printf.fprintf ppf "LessEqI"
|
|
|
|
|
| MoreI -> Printf.fprintf ppf "MoreI"
|
|
|
|
|
| MoreEqI -> Printf.fprintf ppf "MoreEqI"
|
|
|
|
|
and pp_urop (ppf: out_channel) (v: urop) : unit =
|
|
|
|
|
match v with
|
|
|
|
|
Not -> Printf.fprintf ppf "Nop"
|
|
|
|
|
| Copy -> Printf.fprintf ppf "Copy"
|
|
|
|
|
| Rand -> Printf.fprintf ppf "Rand"
|
|
|
|
|
in
|
2024-12-03 17:18:42 +01:00
|
|
|
pp_risci ppf v
|
|
|
|
|
|
|
|
|
|
let pp (ppf: out_channel) (t: t) : unit =
|
|
|
|
|
Printf.fprintf ppf "Input Val: ";
|
2025-01-11 20:32:11 +01:00
|
|
|
( match t.inputval with
|
|
|
|
|
None -> Printf.fprintf ppf "None\n"
|
|
|
|
|
| Some i -> Printf.fprintf ppf "Some %d\n" i );
|
|
|
|
|
Printf.fprintf ppf "Input/Output Registers: ";
|
|
|
|
|
( match t.inputoutputreg with
|
2025-01-27 01:17:53 +01:00
|
|
|
| None ->
|
|
|
|
|
Printf.fprintf ppf "None\n"
|
|
|
|
|
| Some (i, o) ->
|
|
|
|
|
Printf.fprintf ppf "[i: Some r%s, o: Some r%s]\n" i.index o.index);
|
2024-12-03 17:18:42 +01:00
|
|
|
Printf.fprintf ppf "Code:\n";
|
|
|
|
|
List.iter (pp_risci ppf) t.code
|
2024-12-01 12:55:20 +01:00
|
|
|
end
|
|
|
|
|
|
2025-01-27 01:17:53 +01:00
|
|
|
let convert_cfgrisc_risci (i: CfgRISC.RISCSimpleStatements.t list) :
|
|
|
|
|
(RISCAssembly.risci list) =
|
2025-01-27 16:28:23 +01:00
|
|
|
let rec aux (i: CfgRISC.RISCSimpleStatements.t)
|
2025-01-27 01:17:53 +01:00
|
|
|
: RISCAssembly.risci =
|
2024-12-01 12:55:20 +01:00
|
|
|
match i with
|
|
|
|
|
| Nop -> Nop
|
2025-01-27 16:28:23 +01:00
|
|
|
| BRegOp (brop, r1, r2, r3) -> BRegOp (aux_brop brop,
|
2024-12-01 12:55:20 +01:00
|
|
|
{index = r1.index},
|
|
|
|
|
{index = r2.index},
|
|
|
|
|
{index = r3.index})
|
2025-01-27 16:28:23 +01:00
|
|
|
| BImmOp (biop, r1, imm, r3) -> BImmOp (aux_biop biop,
|
2024-12-01 12:55:20 +01:00
|
|
|
{index = r1.index},
|
|
|
|
|
imm,
|
|
|
|
|
{index = r3.index})
|
2025-01-27 16:28:23 +01:00
|
|
|
| URegOp (urop, r1, r3) -> URegOp (aux_urop urop,
|
2024-12-01 12:55:20 +01:00
|
|
|
{index = r1.index},
|
|
|
|
|
{index = r3.index})
|
|
|
|
|
| Load (r1, r3) -> Load ({index = r1.index},
|
|
|
|
|
{index = r3.index})
|
2024-12-16 05:15:33 +01:00
|
|
|
| LoadI (imm, r3) -> LoadI (imm,
|
|
|
|
|
{index = r3.index})
|
2024-12-01 12:55:20 +01:00
|
|
|
| Store (r1, r3) -> Store ({index = r1.index},
|
|
|
|
|
{index = r3.index})
|
2025-01-27 16:28:23 +01:00
|
|
|
and aux_brop (brop: CfgRISC.RISCSimpleStatements.brop)
|
2025-01-27 01:17:53 +01:00
|
|
|
: RISCAssembly.brop =
|
2024-12-01 12:55:20 +01:00
|
|
|
match brop with
|
|
|
|
|
| Add -> Add
|
|
|
|
|
| Sub -> Sub
|
|
|
|
|
| Mult -> Mult
|
|
|
|
|
| Div -> Div
|
|
|
|
|
| Mod -> Mod
|
|
|
|
|
| Pow -> Pow
|
|
|
|
|
| And -> And
|
|
|
|
|
| Or -> Or
|
|
|
|
|
| Eq -> Eq
|
|
|
|
|
| Less -> Less
|
|
|
|
|
| LessEq -> LessEq
|
|
|
|
|
| More -> More
|
|
|
|
|
| MoreEq -> MoreEq
|
2025-01-27 16:28:23 +01:00
|
|
|
and aux_biop (biop: CfgRISC.RISCSimpleStatements.biop)
|
2025-01-27 01:17:53 +01:00
|
|
|
: RISCAssembly.biop =
|
2024-12-01 12:55:20 +01:00
|
|
|
match biop with
|
|
|
|
|
| AddI -> AddI
|
|
|
|
|
| SubI -> SubI
|
|
|
|
|
| MultI -> MultI
|
|
|
|
|
| DivI -> DivI
|
|
|
|
|
| ModI -> ModI
|
|
|
|
|
| PowI -> PowI
|
|
|
|
|
| AndI -> AndI
|
|
|
|
|
| OrI -> OrI
|
|
|
|
|
| EqI -> EqI
|
|
|
|
|
| LessI -> LessI
|
|
|
|
|
| LessEqI -> LessEqI
|
|
|
|
|
| MoreI -> MoreI
|
|
|
|
|
| MoreEqI -> MoreEqI
|
2025-01-27 16:28:23 +01:00
|
|
|
and aux_urop (urop: CfgRISC.RISCSimpleStatements.urop)
|
2025-01-27 01:17:53 +01:00
|
|
|
: RISCAssembly.urop =
|
2024-12-01 12:55:20 +01:00
|
|
|
match urop with
|
|
|
|
|
| Not -> Not
|
|
|
|
|
| Copy -> Copy
|
|
|
|
|
| Rand -> Rand
|
|
|
|
|
in
|
2025-01-27 16:28:23 +01:00
|
|
|
List.map aux i
|
2024-12-01 12:55:20 +01:00
|
|
|
|
2025-01-27 16:28:23 +01:00
|
|
|
let next_common_successor
|
2025-01-27 01:17:53 +01:00
|
|
|
(prg: CfgRISC.RISCCfg.t)
|
|
|
|
|
(node1: Cfg.Node.t)
|
|
|
|
|
(node2: Cfg.Node.t)
|
|
|
|
|
: Cfg.Node.t option =
|
2024-12-01 12:55:20 +01:00
|
|
|
(* Assume the two input nodes are the two branches of an if then else
|
|
|
|
|
statement, then create the two lists that represent the runs until the
|
|
|
|
|
terminal node by choosing always the false statement in guard statements
|
|
|
|
|
(if the guard is for a while statement it gets ignored, if it is for an
|
|
|
|
|
if then else it chooses one of the branches) then find the first common
|
|
|
|
|
node in the lists
|
|
|
|
|
*)
|
|
|
|
|
let rec walk (node: Cfg.Node.t) : Cfg.Node.t list =
|
|
|
|
|
node :: match Cfg.NodeMap.find_opt node prg.edges with
|
|
|
|
|
| None -> []
|
|
|
|
|
| Some (edge, None) -> (walk edge)
|
|
|
|
|
| Some (_, Some edge) -> (walk edge)
|
|
|
|
|
in
|
|
|
|
|
|
|
|
|
|
let list1 = walk node1 in
|
|
|
|
|
let list2 = walk node2 in
|
|
|
|
|
let common = List.filter (fun x -> List.mem x list2) list1 in
|
|
|
|
|
match common with
|
|
|
|
|
[] -> None
|
|
|
|
|
| a::_ -> Some a
|
|
|
|
|
|
|
|
|
|
|
2025-01-27 16:28:23 +01:00
|
|
|
let rec helper_convert
|
2024-12-02 14:26:05 +01:00
|
|
|
(prg: CfgRISC.RISCCfg.t)
|
2025-01-27 16:28:23 +01:00
|
|
|
(current_node: Cfg.Node.t)
|
|
|
|
|
(already_visited: Cfg.Node.t list)
|
2024-12-03 17:18:42 +01:00
|
|
|
: (RISCAssembly.risci list) * (Cfg.Node.t list) =
|
2024-12-02 14:26:05 +01:00
|
|
|
(* takes the program, the current node and a list of already visited nodes to
|
|
|
|
|
compute the linearized three address instructions and the list of
|
|
|
|
|
previoulsy visited nodes plus the newly visited nodes. Stops as soon if
|
|
|
|
|
node has already been visited or if no nodes are next *)
|
2025-01-27 16:28:23 +01:00
|
|
|
if List.mem current_node already_visited then
|
|
|
|
|
([], already_visited)
|
2024-12-01 12:55:20 +01:00
|
|
|
else (
|
2025-01-27 16:28:23 +01:00
|
|
|
let nextnodes = (Cfg.NodeMap.find_opt current_node prg.edges) in
|
2024-12-02 00:45:24 +01:00
|
|
|
let currentcode =
|
2025-01-27 16:28:23 +01:00
|
|
|
(match (Cfg.NodeMap.find_opt current_node prg.content) with
|
2024-12-02 00:45:24 +01:00
|
|
|
| None -> []
|
|
|
|
|
| Some x -> convert_cfgrisc_risci x)
|
|
|
|
|
in
|
2024-12-01 12:55:20 +01:00
|
|
|
match nextnodes with
|
|
|
|
|
| Some (nextnode1, None) ->
|
2025-01-27 16:28:23 +01:00
|
|
|
let res, vis =
|
|
|
|
|
helper_convert
|
|
|
|
|
prg
|
|
|
|
|
nextnode1
|
|
|
|
|
(current_node :: already_visited)
|
|
|
|
|
in
|
2024-12-01 12:55:20 +01:00
|
|
|
(currentcode @ res, vis)
|
|
|
|
|
| Some (nextnode1, Some nextnode2) -> (
|
2025-01-27 16:28:23 +01:00
|
|
|
let ncs = next_common_successor prg nextnode1 nextnode2 in
|
2024-12-01 12:55:20 +01:00
|
|
|
match ncs with
|
|
|
|
|
| None -> (* should never happen since the terminal node should always be
|
|
|
|
|
rechable *)
|
|
|
|
|
failwith "Topology got a little mixed up"
|
|
|
|
|
| Some ncs -> (
|
|
|
|
|
if (ncs.id = nextnode2.id)
|
2024-12-02 14:26:05 +01:00
|
|
|
then (* while or for loop, three labels are necessary *)
|
|
|
|
|
let label1 = nextLabel () in
|
|
|
|
|
let label2 = nextLabel () in
|
|
|
|
|
let label3 = nextLabel () in
|
|
|
|
|
|
2025-01-27 01:17:53 +01:00
|
|
|
let res1, _ =
|
2025-01-27 16:28:23 +01:00
|
|
|
(helper_convert prg nextnode1
|
|
|
|
|
(current_node :: nextnode2 :: already_visited)) in
|
2025-01-27 01:17:53 +01:00
|
|
|
let res2, vis2 =
|
2025-01-27 16:28:23 +01:00
|
|
|
(helper_convert prg nextnode2
|
|
|
|
|
(current_node :: nextnode1 :: already_visited)) in
|
2024-12-02 14:26:05 +01:00
|
|
|
|
|
|
|
|
match List.nth currentcode ((List.length currentcode) - 1) with
|
|
|
|
|
| BRegOp (_, _, _, r)
|
|
|
|
|
| BImmOp (_, _, _, r)
|
|
|
|
|
| URegOp (_, _, r)
|
|
|
|
|
| Load (_, r)
|
2025-01-11 20:32:11 +01:00
|
|
|
| Store (r, _)
|
2025-01-27 01:17:53 +01:00
|
|
|
| LoadI (_, r) -> (([Label label1]
|
|
|
|
|
: RISCAssembly.risci list) @
|
2024-12-02 14:26:05 +01:00
|
|
|
currentcode @
|
2025-01-27 01:17:53 +01:00
|
|
|
([CJump (r, label2, label3); Label label2]
|
|
|
|
|
: RISCAssembly.risci list) @
|
2024-12-02 14:26:05 +01:00
|
|
|
res1 @
|
2025-01-27 01:17:53 +01:00
|
|
|
([Jump label1; Label label3]
|
|
|
|
|
: RISCAssembly.risci list) @
|
2024-12-02 14:26:05 +01:00
|
|
|
res2
|
|
|
|
|
, vis2)
|
2024-12-03 17:18:42 +01:00
|
|
|
| _ -> failwith "Missing instruction at branch"
|
2024-12-02 14:26:05 +01:00
|
|
|
else (* if branches, three labels are necessary *)
|
2024-12-01 12:55:20 +01:00
|
|
|
let label1 = nextLabel () in
|
|
|
|
|
let label2 = nextLabel () in
|
|
|
|
|
let label3 = nextLabel () in
|
|
|
|
|
|
2025-01-27 01:17:53 +01:00
|
|
|
let res1, vis1 =
|
2025-01-27 16:28:23 +01:00
|
|
|
helper_convert
|
|
|
|
|
prg
|
|
|
|
|
nextnode1
|
|
|
|
|
(current_node :: ncs :: already_visited)
|
|
|
|
|
in
|
|
|
|
|
let res2, _ = helper_convert prg nextnode2 vis1 in
|
|
|
|
|
let res3, vis3 =
|
|
|
|
|
helper_convert prg ncs (current_node :: already_visited)
|
|
|
|
|
in
|
2024-12-01 12:55:20 +01:00
|
|
|
match List.nth currentcode ((List.length currentcode) - 1) with
|
|
|
|
|
| BRegOp (_, _, _, r)
|
|
|
|
|
| BImmOp (_, _, _, r)
|
|
|
|
|
| URegOp (_, _, r)
|
|
|
|
|
| Load (_, r)
|
2025-01-11 20:32:11 +01:00
|
|
|
| Store (r, _)
|
2024-12-16 05:15:33 +01:00
|
|
|
| LoadI (_, r) -> (currentcode @
|
2025-01-27 01:17:53 +01:00
|
|
|
([CJump (r, label1, label2); Label label1]
|
|
|
|
|
: RISCAssembly.risci list) @
|
2024-12-01 12:55:20 +01:00
|
|
|
res1 @
|
2025-01-27 01:17:53 +01:00
|
|
|
([Jump label3; Label label2]
|
|
|
|
|
: RISCAssembly.risci list) @
|
2024-12-01 12:55:20 +01:00
|
|
|
res2 @
|
2025-01-27 01:17:53 +01:00
|
|
|
([Label label3]
|
|
|
|
|
: RISCAssembly.risci list) @
|
2024-12-01 12:55:20 +01:00
|
|
|
res3
|
|
|
|
|
, vis3)
|
2024-12-03 17:18:42 +01:00
|
|
|
| _ -> failwith "Missing instruction at branch"
|
2024-12-01 12:55:20 +01:00
|
|
|
)
|
|
|
|
|
)
|
2025-01-27 16:28:23 +01:00
|
|
|
| None -> (currentcode, current_node :: already_visited)
|
2024-12-01 12:55:20 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
let convert (prg: CfgRISC.RISCCfg.t) : RISCAssembly.t =
|
2025-01-27 16:28:23 +01:00
|
|
|
{code = (helper_convert prg (Option.get prg.initial) [] |> fst |>
|
2024-12-03 17:18:42 +01:00
|
|
|
List.append ([Label "main"] : RISCAssembly.risci list));
|
2025-01-27 16:28:23 +01:00
|
|
|
inputval = prg.input_val;
|
2024-12-27 21:11:38 +01:00
|
|
|
inputoutputreg =
|
2025-01-27 16:28:23 +01:00
|
|
|
match prg.input_output_var with
|
2024-12-27 21:11:38 +01:00
|
|
|
None -> None
|
|
|
|
|
| Some (i, o) -> Some ({index = i}, {index = o})
|
|
|
|
|
}
|