Skip to content

Commit daa2d91

Browse files
committed
CLI: Parse isla's section part
1 parent 3c786f5 commit daa2d91

7 files changed

Lines changed: 127 additions & 7 deletions

File tree

cli/lib/isla/converter.ml

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,21 @@ let build_data_memory syms sym addr init_value =
154154
}
155155

156156
let to_testrepr (ir : Ir.t) : Testrepr.t =
157+
(* Assemble sections first and reserve their address ranges *)
158+
let assembled_sections =
159+
List.map
160+
(fun (sec : Ir.section) ->
161+
let enc = Assembler.assemble sec.code in
162+
(sec, enc))
163+
ir.sections
164+
in
157165
let syms = Symbols.empty () in
166+
List.iter
167+
(fun (sec, enc) ->
168+
Symbols.reserve syms sec.Ir.address (Bytes.length enc))
169+
assembled_sections;
158170
List.iter (Symbols.alloc_sym syms) ir.symbolic;
159-
let encoded_threads =
171+
let assembled_threads =
160172
List.map
161173
(fun (thread : Ir.thread) ->
162174
let enc = Assembler.assemble thread.code in
@@ -169,12 +181,17 @@ let to_testrepr (ir : Ir.t) : Testrepr.t =
169181
List.map
170182
(fun (thread, _, code_addr) ->
171183
build_registers syms ~arch:ir.arch code_addr thread)
172-
encoded_threads
184+
assembled_threads
173185
in
174186
let code_memory =
175187
List.map
176188
(fun (_, enc, code_addr) -> build_code_memory ~step:code_step code_addr enc)
177-
encoded_threads
189+
assembled_threads
190+
in
191+
let section_memory =
192+
List.map
193+
(fun (sec, enc) -> build_code_memory ~step:code_step sec.Ir.address enc)
194+
assembled_sections
178195
in
179196
let data_memory =
180197
List.map (fun sym ->
@@ -202,7 +219,7 @@ let to_testrepr (ir : Ir.t) : Testrepr.t =
202219
(fun (_, enc, code_addr) ->
203220
let end_pc = Z.of_int (code_addr + Bytes.length enc) in
204221
[(pc, RegValGen.Number end_pc)])
205-
encoded_threads
222+
assembled_threads
206223
in
207224
let finals =
208225
to_final_conds
@@ -215,7 +232,7 @@ let to_testrepr (ir : Ir.t) : Testrepr.t =
215232
arch = Litmus.Arch_id.to_string ir.arch;
216233
name = ir.name;
217234
registers;
218-
memory = code_memory @ data_memory;
235+
memory = code_memory @ section_memory @ data_memory;
219236
term_cond;
220237
finals;
221238
}

cli/lib/isla/ir.ml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ type thread = {
1212
init : (string * value) list;
1313
}
1414

15+
type section = {
16+
sec_name : string;
17+
address : int;
18+
code : string;
19+
}
20+
1521
type expect =
1622
| Sat
1723
| Unsat
@@ -20,6 +26,7 @@ type t = {
2026
arch : Litmus.Arch_id.t;
2127
name : string;
2228
threads : thread list;
29+
sections : section list;
2330
symbolic : string list;
2431
locations : (string * value) list;
2532
expect : expect;
@@ -53,6 +60,27 @@ let parse_threads toml =
5360
let table = Otoml.get_table toml in
5461
List.sort (fun a b -> compare a.tid b.tid) (List.map parse_thread table)
5562

63+
let parse_address = function
64+
| Otoml.TomlInteger i -> i
65+
| Otoml.TomlString s ->
66+
(try Z.to_int (Z.of_string s)
67+
with Invalid_argument _ ->
68+
raise (Otoml.Type_error ("invalid address: " ^ s)))
69+
| v ->
70+
raise (Otoml.Type_error
71+
("address must be integer or hex string, got: " ^
72+
Otoml.Printer.to_string v))
73+
74+
let parse_section (name, table) =
75+
let _ = Otoml.get_table table in
76+
let address = Otoml.find table parse_address ["address"] in
77+
let code = Otoml.find table Otoml.get_string ["code"] |> String.trim in
78+
{ sec_name = name; address; code }
79+
80+
let parse_sections toml =
81+
let table = Otoml.get_table toml in
82+
List.map parse_section table
83+
5684
let parse_expect toml =
5785
match Otoml.get_string toml with
5886
| "sat" -> Sat
@@ -85,6 +113,8 @@ let of_toml toml =
85113
arch = Otoml.find toml parse_arch ["arch"];
86114
name = Otoml.find_or ~default:"unknown" toml Otoml.get_string ["name"];
87115
threads = Otoml.find toml parse_threads ["thread"];
116+
sections =
117+
Otoml.find_or ~default:[] toml parse_sections ["section"];
88118
symbolic =
89119
Otoml.find_or ~default:[] toml (Otoml.get_array Otoml.get_string) ["symbolic"];
90120
locations = Otoml.find_or ~default:[] toml (Otoml.get_table_values parse_value) ["locations"];

cli/lib/isla/symbols.ml

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
type t = {
44
mutable next_addr : int;
55
mutable table : (string * int) list;
6+
mutable reserved : (int * int) list; (** (addr, size) pairs for reserved ranges *)
67
}
78

89
let resolve_opt t name = List.assoc_opt name t.table
@@ -26,12 +27,25 @@ let base_addr () =
2627
let empty () = {
2728
next_addr = base_addr ();
2829
table = [];
30+
reserved = [];
2931
}
3032

33+
let overlaps addr size (r_addr, r_size) =
34+
addr < r_addr + r_size && r_addr < addr + size
35+
36+
let reserve t addr size =
37+
t.reserved <- (addr, size) :: t.reserved
38+
3139
let alloc_page t =
3240
let page_size = page_size () in
33-
let addr = t.next_addr in
34-
t.next_addr <- (addr + page_size);
41+
let rec find_free addr =
42+
if List.exists (overlaps addr page_size) t.reserved then
43+
find_free (addr + page_size)
44+
else
45+
addr
46+
in
47+
let addr = find_free t.next_addr in
48+
t.next_addr <- addr + page_size;
3549
addr
3650

3751
let alloc_sym t name =

cli/tests/unit/isla/converter_test.ml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,27 @@ let tests =
135135
}
136136
in
137137
assert_equal expected (convert mp_toml));
138+
"section: assembled at explicit address" >:: (fun _ ->
139+
Test_utils.setup ();
140+
let toml = Otoml.Parser.from_string {|
141+
arch = "AArch64"
142+
name = "WithSection"
143+
symbolic = ["x"]
144+
145+
[thread.0]
146+
init = { X0 = "x" }
147+
code = "NOP"
148+
149+
[section.handler]
150+
address = "0x1400"
151+
code = "MOV X2, #1"
152+
|} in
153+
let repr = convert toml in
154+
let sec_block =
155+
List.find (fun (b : Testrepr.memory_block) -> b.addr = 0x1400) repr.memory
156+
in
157+
assert_equal Testrepr.Code sec_block.kind;
158+
assert_equal 4 (Bytes.length sec_block.data));
138159
"e2e: SimpleStore seq" >:: (fun _ ->
139160
Test_utils.setup ();
140161
let result, _msgs =

cli/tests/unit/isla/ir_test.ml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ code = """
2828
STR W0,[X1]
2929
"""
3030

31+
[section.el1_handler]
32+
address = "0x1400"
33+
code = """
34+
MOV X2, #1
35+
ERET
36+
"""
37+
3138
[final]
3239
expect = "sat"
3340
assertion = "1:X0 = 1 & *y = 1"
@@ -51,6 +58,8 @@ let expected : Isla.Ir.t =
5158
init = [ ("X1", Isla.Ir.Sym "y"); ("X2", Isla.Ir.Sym "x") ];
5259
};
5360
];
61+
sections =
62+
[{ sec_name = "el1_handler"; address = 0x1400; code = "MOV X2, #1\n ERET" }];
5463
symbolic = [ "x"; "y" ];
5564
locations = [ ("x", Isla.Ir.Int Z.zero); ("y", Isla.Ir.Int Z.zero) ];
5665
expect = Isla.Ir.Sat;

cli/tests/unit/isla/normalize_test.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ let sample_ir arch : Isla.Ir.t =
1515
init = [ ("X0", Isla.Ir.Sym "x"); ("W2", Isla.Ir.Int (Z.of_int 3)) ];
1616
};
1717
];
18+
sections = [{ sec_name = "handler"; address = 0x1400; code = "MOV X2, #1" }];
1819
symbolic = [ "x" ];
1920
locations = [ ("x", Isla.Ir.Int Z.zero) ];
2021
expect = Isla.Ir.Sat;

cli/tests/unit/isla/symbols_test.ml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,34 @@ let tests =
3131
let a1 = Isla.Symbols.resolve_or_alloc s0 "x" in
3232
let a2 = Isla.Symbols.resolve_or_alloc s0 "x" in
3333
assert_equal a1 a2);
34+
"alloc skips reserved range" >:: (fun _ ->
35+
Test_utils.setup ();
36+
let s = Isla.Symbols.empty () in
37+
Isla.Symbols.reserve s 0x500 4;
38+
let addr = Isla.Symbols.resolve_or_alloc s "x" in
39+
assert_equal 0x1500 addr);
40+
"alloc skips multiple reserved ranges" >:: (fun _ ->
41+
Test_utils.setup ();
42+
let s = Isla.Symbols.empty () in
43+
Isla.Symbols.reserve s 0x500 4;
44+
Isla.Symbols.reserve s 0x1500 4;
45+
let addr = Isla.Symbols.resolve_or_alloc s "x" in
46+
assert_equal 0x2500 addr);
47+
"alloc skips reserved then continues normally" >:: (fun _ ->
48+
Test_utils.setup ();
49+
let s = Isla.Symbols.empty () in
50+
Isla.Symbols.reserve s 0x500 4;
51+
let a1 = Isla.Symbols.resolve_or_alloc s "x" in
52+
let a2 = Isla.Symbols.resolve_or_alloc s "y" in
53+
assert_equal 0x1500 a1;
54+
assert_equal 0x2500 a2);
55+
"reserved range overlapping middle of page skips it" >:: (fun _ ->
56+
Test_utils.setup ();
57+
let s = Isla.Symbols.empty () in
58+
(* reserve range that overlaps with the first page [0x500, 0x1500) *)
59+
Isla.Symbols.reserve s 0x1000 0x100;
60+
let addr = Isla.Symbols.resolve_or_alloc s "x" in
61+
assert_equal 0x1500 addr);
3462
]
3563

3664
let () = run_test_tt_main tests

0 commit comments

Comments
 (0)