Skip to content

Commit 2258d7d

Browse files
committed
Avoid implicit casts to string
Can have unintended consequences, due to how overloading interacts with casts. For example, x : X == y : X can be interpreted as eq_string(cast(x), cast(y)) if x and y are both castable to string, even when there is an equality function (X, X) -> bool. Sail->SMT can't handle strings very well so it's best to just ensure that this can never occur. Rather than implicitly casting in logging statements like: print("xyz" ^ x ^ " foo " ^ y) it's now print("xyz" ^ to_str(x) ^ " foo " ^ to_str(y)) which ensures that the conversion to strings only happens where intended. I also added a warning to Sail itself to try to catch these cases in future.
1 parent 83c3ec6 commit 2258d7d

11 files changed

+36
-20
lines changed

model/prelude.sail

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ val string_take = "string_take" : (string, nat) -> string
1313
val string_length = "string_length" : string -> nat
1414
val string_append = {c: "concat_str", _: "string_append"} : (string, string) -> string
1515

16-
val eq_anything = {ocaml: "(fun (x, y) -> x = y)", interpreter: "eq_anything", lem: "eq", coq: "generic_eq"} : forall ('a : Type). ('a, 'a) -> bool
16+
val eq_anything = {ocaml: "(fun (x, y) -> x = y)", interpreter: "eq_anything", lem: "eq", coq: "generic_eq", c: "eq_anything"} : forall ('a : Type). ('a, 'a) -> bool
1717

1818
overload operator == = {eq_string, eq_anything}
1919

model/riscv_csr_map.sail

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* Mapping of csr addresses to their names. */
22

3-
val cast csr_name : csreg -> string
3+
val csr_name : csreg -> string
44
function csr_name(csr) = {
55
match (csr) {
66
/* user trap setup */
@@ -76,6 +76,8 @@ function csr_name(csr) = {
7676
}
7777
}
7878

79+
overload to_str = {csr_name}
80+
7981
mapping csr_name_map : csreg <-> string = {
8082
/* user trap setup */
8183
0x000 <-> "ustatus",

model/riscv_insts_end.sail

+3-1
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@ end assembly
2929
end encdec
3030
end encdec_compressed
3131

32-
val cast print_insn : ast -> string
32+
val print_insn : ast -> string
3333
function print_insn insn = assembly(insn)
3434

35+
overload to_str = {print_insn}
36+
3537
val decode : bits(32) -> ast effect pure
3638
function decode bv = encdec(bv)
3739

model/riscv_insts_zicsr.sail

+2-2
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ function readCSR csr : csreg -> xlenbits = {
9494
EXTZ(0x0) }
9595
}
9696
};
97-
print_reg("CSR " ^ csr ^ " -> " ^ BitStr(res));
97+
print_reg("CSR " ^ to_str(csr) ^ " -> " ^ BitStr(res));
9898
res
9999
}
100100

@@ -164,7 +164,7 @@ function writeCSR (csr : csreg, value : xlenbits) -> unit = {
164164
_ => None()
165165
};
166166
match res {
167-
Some(v) => print_reg("CSR " ^ csr ^ " <- " ^ BitStr(v) ^ " (input: " ^ BitStr(value) ^ ")"),
167+
Some(v) => print_reg("CSR " ^ to_str(csr) ^ " <- " ^ BitStr(v) ^ " (input: " ^ BitStr(value) ^ ")"),
168168
None() => { /* check extensions */
169169
if ext_write_CSR(csr, value)
170170
then ()

model/riscv_mem.sail

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ function phys_mem_read forall 'n, 'n > 0. (t : AccessType, addr : xlenbits, widt
3636
(Read, None()) => MemException(E_Load_Access_Fault),
3737
(_, None()) => MemException(E_SAMO_Access_Fault),
3838
(_, Some(v)) => { if get_config_print_mem()
39-
then print_mem("mem[" ^ t ^ "," ^ BitStr(addr) ^ "] -> " ^ BitStr(v));
39+
then print_mem("mem[" ^ to_str(t) ^ "," ^ BitStr(addr) ^ "] -> " ^ BitStr(v));
4040
MemValue(v) }
4141
}
4242
}

model/riscv_next_control.sail

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ function write_NExt_CSR(csr : csreg, value : xlenbits) -> bool = {
4747
_ => None()
4848
};
4949
match res {
50-
Some(v) => { print_reg("CSR " ^ csr ^ " <- " ^ BitStr(v) ^ " (input: " ^ BitStr(value) ^ ")");
50+
Some(v) => { print_reg("CSR " ^ to_str(csr) ^ " <- " ^ BitStr(v) ^ " (input: " ^ BitStr(value) ^ ")");
5151
true },
5252
None() => false
5353
}

model/riscv_regs.sail

+3-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ overload X = {rX, wX}
143143

144144
/* register names */
145145

146-
val cast reg_name_abi : regidx -> string
146+
val reg_name_abi : regidx -> string
147147

148148
function reg_name_abi(r) = {
149149
match (r) {
@@ -182,6 +182,8 @@ function reg_name_abi(r) = {
182182
}
183183
}
184184

185+
overload to_str = {reg_name_abi}
186+
185187
/* mappings for assembly */
186188

187189
val reg_name : bits(5) <-> string

model/riscv_step.sail

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ function step(step_no) = {
3333
F_RVC(h) => {
3434
let ast = decodeCompressed(h);
3535
if get_config_print_instr() then {
36-
print_instr("[" ^ string_of_int(step_no) ^ "] [" ^ cur_privilege ^ "]: " ^ BitStr(PC) ^ " (" ^ BitStr(h) ^ ") " ^ ast);
36+
print_instr("[" ^ string_of_int(step_no) ^ "] [" ^ to_str(cur_privilege) ^ "]: " ^ BitStr(PC) ^ " (" ^ BitStr(h) ^ ") " ^ to_str(ast));
3737
};
3838
/* check for RVC once here instead of every RVC execute clause. */
3939
if haveRVC() then {
@@ -47,7 +47,7 @@ function step(step_no) = {
4747
F_Base(w) => {
4848
let ast = decode(w);
4949
if get_config_print_instr() then {
50-
print_instr("[" ^ string_of_int(step_no) ^ "] [" ^ cur_privilege ^ "]: " ^ BitStr(PC) ^ " (" ^ BitStr(w) ^ ") " ^ ast);
50+
print_instr("[" ^ string_of_int(step_no) ^ "] [" ^ to_str(cur_privilege) ^ "]: " ^ BitStr(PC) ^ " (" ^ BitStr(w) ^ ") " ^ to_str(ast));
5151
};
5252
nextPC = PC + 4;
5353
(execute(ext_post_decode_hook(ast)), true)

model/riscv_sys_control.sail

+8-6
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,8 @@ function trap_handler(del_priv : Privilege, intr : bool, c : exc_code, pc : xlen
296296
-> xlenbits = {
297297
rvfi_trap();
298298
print_platform("handling " ^ (if intr then "int#" else "exc#")
299-
^ BitStr(c) ^ " at priv " ^ del_priv ^ " with tval " ^ BitStr(tval(info)));
299+
^ BitStr(c) ^ " at priv " ^ to_str(del_priv)
300+
^ " with tval " ^ BitStr(tval(info)));
300301

301302
cancel_reservation();
302303

@@ -370,8 +371,8 @@ function exception_handler(cur_priv : Privilege, ctl : ctl_result,
370371
match (cur_priv, ctl) {
371372
(_, CTL_TRAP(e)) => {
372373
let del_priv = exception_delegatee(e.trap, cur_priv);
373-
print_platform("trapping from " ^ cur_priv ^ " to " ^ del_priv
374-
^ " to handle " ^ e.trap);
374+
print_platform("trapping from " ^ to_str(cur_priv) ^ " to " ^ to_str(del_priv)
375+
^ " to handle " ^ to_str(e.trap));
375376
trap_handler(del_priv, false, e.trap, pc, e.excinfo, e.ext)
376377
},
377378
(_, CTL_MRET()) => {
@@ -382,7 +383,7 @@ function exception_handler(cur_priv : Privilege, ctl : ctl_result,
382383
mstatus->MPP() = privLevel_to_bits(if haveUsrMode() then User else Machine);
383384

384385
print_reg("CSR mstatus <- " ^ BitStr(mstatus.bits()));
385-
print_platform("ret-ing from " ^ prev_priv ^ " to " ^ cur_privilege);
386+
print_platform("ret-ing from " ^ to_str(prev_priv) ^ " to " ^ to_str(cur_privilege));
386387

387388
cancel_reservation();
388389
prepare_xret_target(Machine) & pc_alignment_mask()
@@ -396,7 +397,8 @@ function exception_handler(cur_priv : Privilege, ctl : ctl_result,
396397
mstatus->SPP() = false;
397398

398399
print_reg("CSR mstatus <- " ^ BitStr(mstatus.bits()));
399-
print_platform("ret-ing from " ^ prev_priv ^ " to " ^ cur_privilege);
400+
print_platform("ret-ing from " ^ to_str(prev_priv)
401+
^ " to " ^ to_str(cur_privilege));
400402

401403
cancel_reservation();
402404
prepare_xret_target(Supervisor) & pc_alignment_mask()
@@ -408,7 +410,7 @@ function exception_handler(cur_priv : Privilege, ctl : ctl_result,
408410
cur_privilege = User;
409411

410412
print_reg("CSR mstatus <- " ^ BitStr(mstatus.bits()));
411-
print_platform("ret-ing from " ^ prev_priv ^ " to " ^ cur_privilege);
413+
print_platform("ret-ing from " ^ to_str(prev_priv) ^ " to " ^ to_str(cur_privilege));
412414

413415
cancel_reservation();
414416
prepare_xret_target(User) & pc_alignment_mask()

model/riscv_types.sail

+9-3
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,16 @@ function privLevel_of_bits (p) =
8181
0b11 => Machine
8282
}
8383

84-
val cast privLevel_to_str : Privilege -> string
84+
val privLevel_to_str : Privilege -> string
8585
function privLevel_to_str (p) =
8686
match (p) {
8787
User => "U",
8888
Supervisor => "S",
8989
Machine => "M"
9090
}
9191

92+
overload to_str = {privLevel_to_str}
93+
9294
/* enum denoting whether an executed instruction retires */
9395

9496
enum Retired = {RETIRE_SUCCESS, RETIRE_FAIL}
@@ -97,7 +99,7 @@ enum Retired = {RETIRE_SUCCESS, RETIRE_FAIL}
9799

98100
enum AccessType = {Read, Write, ReadWrite, Execute}
99101

100-
val cast accessType_to_str : AccessType -> string
102+
val accessType_to_str : AccessType -> string
101103
function accessType_to_str (a) =
102104
match (a) {
103105
Read => "R",
@@ -106,6 +108,8 @@ function accessType_to_str (a) =
106108
Execute => "X"
107109
}
108110

111+
overload to_str = {accessType_to_str}
112+
109113
enum word_width = {BYTE, HALF, WORD, DOUBLE}
110114

111115
/* architectural interrupt definitions */
@@ -186,7 +190,7 @@ function exceptionType_to_bits(e) =
186190
E_CHERI => 0x20 /* FIXME: this is reserved for a future standard */
187191
}
188192

189-
val cast exceptionType_to_str : ExceptionType -> string
193+
val exceptionType_to_str : ExceptionType -> string
190194
function exceptionType_to_str(e) =
191195
match (e) {
192196
E_Fetch_Addr_Align => "misaligned-fetch",
@@ -210,6 +214,8 @@ function exceptionType_to_str(e) =
210214
E_CHERI => "CHERI"
211215
}
212216

217+
overload to_str = {exceptionType_to_str}
218+
213219
/* model-internal exceptions */
214220

215221
union exception = {

model/riscv_vmem_common.sail

+3-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ enum PTW_Error = {
6767
PTW_Misaligned, /* misaligned superpage */
6868
PTW_PTE_Update /* PTE update needed but not enabled */
6969
}
70-
val cast ptw_error_to_str : PTW_Error -> string
70+
val ptw_error_to_str : PTW_Error -> string
7171
function ptw_error_to_str(e) =
7272
match (e) {
7373
PTW_Access => "mem-access-error",
@@ -77,6 +77,8 @@ function ptw_error_to_str(e) =
7777
PTW_PTE_Update => "pte-update-needed"
7878
}
7979

80+
overload to_str = {ptw_error_to_str}
81+
8082
/* conversion of these translation/PTW failures into architectural exceptions */
8183
function translationException(a : AccessType, f : PTW_Error) -> ExceptionType = {
8284
let e : ExceptionType =

0 commit comments

Comments
 (0)