Skip to content

Commit 279f88c

Browse files
gascheclef-men
authored andcommitted
Add tests for atomic record fields.
1 parent 032dd4c commit 279f88c

File tree

3 files changed

+213
-5
lines changed

3 files changed

+213
-5
lines changed

testsuite/tests/atomic-locs/cmm.compilers.reference

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,43 @@ cmm:
33
(data)
44
(data
55
int 3063
6-
"camlCmm.2":
6+
"camlCmm.4":
77
addr "camlCmm.standard_atomic_get_271"
88
int 72057594037927941)
99
(data
1010
int 4087
11-
"camlCmm.1":
11+
"camlCmm.3":
1212
addr "caml_curry3"
1313
int 216172782113783815
1414
addr "camlCmm.standard_atomic_cas_294")
15-
(data int 2816 global "camlCmm" "camlCmm": int 1 int 1)
15+
(data int 3063 "camlCmm.2": addr "camlCmm.get_302" int 72057594037927941)
16+
(data
17+
int 4087
18+
"camlCmm.1":
19+
addr "caml_curry2"
20+
int 144115188075855879
21+
addr "camlCmm.set_305")
22+
(data int 4864 global "camlCmm" "camlCmm": int 1 int 1 int 1 int 1)
1623
(data global "camlCmm.gc_roots" "camlCmm.gc_roots": addr "camlCmm" int 0)
1724
(function camlCmm.standard_atomic_get_271 (r: val) (load_mut_atomic val r))
1825

1926
(function camlCmm.standard_atomic_cas_294 (r: val oldv: val newv: val)
2027
(extcall "caml_atomic_cas_field" r 1 oldv newv int,int,int,int->val))
2128

29+
(function camlCmm.get_302 (r: val) (load_mut_atomic val (+a r 8)))
30+
31+
(function camlCmm.set_305 (r: val v: val)
32+
(extcall "caml_atomic_exchange_field" r 3 v int,int,int->unit) 1)
33+
2234
(function camlCmm.entry ()
23-
(let standard_atomic_get "camlCmm.2"
35+
(let standard_atomic_get "camlCmm.4"
2436
(extcall "caml_initialize" "camlCmm" standard_atomic_get ->unit))
25-
(let standard_atomic_cas "camlCmm.1"
37+
(let standard_atomic_cas "camlCmm.3"
2638
(extcall "caml_initialize" (+a "camlCmm" 8) standard_atomic_cas ->unit))
39+
(let get "camlCmm.2"
40+
(extcall "caml_initialize" (+a "camlCmm" 16) get ->unit))
41+
(let set "camlCmm.1"
42+
(extcall "caml_initialize" (+a "camlCmm" 24) set ->unit))
2743
1)
2844

2945
(data)

testsuite/tests/atomic-locs/cmm.ml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,17 @@ let standard_atomic_get (r : 'a Atomic.t) =
77
let standard_atomic_cas (r : 'a Atomic.t) oldv newv =
88
Atomic.compare_and_set r oldv newv
99

10+
11+
(* atomic record fields *)
12+
13+
type 'a atomic = { filler : unit; mutable x : 'a [@atomic] }
14+
15+
let get (r : 'a atomic) : 'a =
16+
r.x
17+
18+
let set (r : 'a atomic) v =
19+
r.x <- v
20+
1021
(* TEST
1122
1223
(* we restrict this test to a single configuration,
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
(* TEST
2+
flags = "-dlambda -dno-locations -dno-unique-ids";
3+
expect;
4+
*)
5+
6+
(* Basic usage: redefine atomics. *)
7+
8+
module Basic = struct
9+
type 'a atomic = { mutable filler: unit; mutable x : 'a [@atomic] }
10+
11+
let get (type a) (r : a atomic) : a = r.x
12+
13+
let set (type a) (r : a atomic) (v : a) : unit = r.x <- v
14+
end
15+
[%%expect{|
16+
(apply (field_mut 1 (global Toploop!)) "Basic/290"
17+
(let
18+
(get = (function r (atomic_load r 1))
19+
set = (function r v : int (ignore (caml_atomic_exchange_field r 1 v))))
20+
(makeblock 0 get set)))
21+
module Basic :
22+
sig
23+
type 'a atomic = { mutable filler : unit; mutable x : 'a [@atomic]; }
24+
val get : 'a atomic -> 'a
25+
val set : 'a atomic -> 'a -> unit
26+
end
27+
|}];;
28+
29+
30+
(* Atomic fields must be mutable. *)
31+
module Error = struct
32+
type t = { x : int [@atomic] }
33+
end
34+
[%%expect{|
35+
Line 2, characters 13-30:
36+
2 | type t = { x : int [@atomic] }
37+
^^^^^^^^^^^^^^^^^
38+
Error: The label "x" must be mutable to be declared atomic.
39+
|}];;
40+
41+
42+
(* Check module interface checking: it is not allowed to remove or add
43+
atomic attributes. *)
44+
45+
module Wrong1 = (struct
46+
type t = { mutable x : int }
47+
end : sig
48+
(* adding an 'atomic' attribute missing in the implementation: invalid. *)
49+
type t = { mutable x : int [@atomic] }
50+
end)
51+
[%%expect{|
52+
Lines 1-3, characters 17-3:
53+
1 | .................struct
54+
2 | type t = { mutable x : int }
55+
3 | end......
56+
Error: Signature mismatch:
57+
Modules do not match:
58+
sig type t = { mutable x : int; } end
59+
is not included in
60+
sig type t = { mutable x : int [@atomic]; } end
61+
Type declarations do not match:
62+
type t = { mutable x : int; }
63+
is not included in
64+
type t = { mutable x : int [@atomic]; }
65+
Fields do not match:
66+
"mutable x : int;"
67+
is not the same as:
68+
"mutable x : int [@atomic];"
69+
The second is atomic and the first is not.
70+
|}];;
71+
72+
module Wrong2 = (struct
73+
type t = { mutable x : int [@atomic] }
74+
end : sig
75+
(* removing an 'atomic' attribute present in the implementation: invalid. *)
76+
type t = { mutable x : int }
77+
end)
78+
[%%expect{|
79+
Lines 1-3, characters 17-3:
80+
1 | .................struct
81+
2 | type t = { mutable x : int [@atomic] }
82+
3 | end......
83+
Error: Signature mismatch:
84+
Modules do not match:
85+
sig type t = { mutable x : int [@atomic]; } end
86+
is not included in
87+
sig type t = { mutable x : int; } end
88+
Type declarations do not match:
89+
type t = { mutable x : int [@atomic]; }
90+
is not included in
91+
type t = { mutable x : int; }
92+
Fields do not match:
93+
"mutable x : int [@atomic];"
94+
is not the same as:
95+
"mutable x : int;"
96+
The first is atomic and the second is not.
97+
|}];;
98+
99+
module Ok = (struct
100+
type t = { mutable x : int [@atomic] }
101+
end : sig
102+
type t = { mutable x : int [@atomic] }
103+
end)
104+
[%%expect{|
105+
(apply (field_mut 1 (global Toploop!)) "Ok/306" (makeblock 0))
106+
module Ok : sig type t = { mutable x : int [@atomic]; } end
107+
|}];;
108+
109+
110+
111+
(* Inline records are supported, including in extensions. *)
112+
113+
module Inline_record = struct
114+
type t = A of { mutable x : int [@atomic] }
115+
116+
let test : t -> int = fun (A r) -> r.x
117+
end
118+
[%%expect{|
119+
(apply (field_mut 1 (global Toploop!)) "Inline_record/314"
120+
(let (test = (function param : int (atomic_load param 0)))
121+
(makeblock 0 test)))
122+
module Inline_record :
123+
sig type t = A of { mutable x : int [@atomic]; } val test : t -> int end
124+
|}];;
125+
126+
module Extension_with_inline_record = struct
127+
type t = ..
128+
type t += A of { mutable x : int [@atomic] }
129+
130+
(* one should see in the -dlambda output below that the field offset is not 0
131+
as one could expect, but 1, due to an extra argument in extensible variants. *)
132+
let test : t -> int = function
133+
| A r -> r.x
134+
| _ -> 0
135+
136+
let () = assert (test (A { x = 42 }) = 42)
137+
end
138+
[%%expect{|
139+
(apply (field_mut 1 (global Toploop!)) "Extension_with_inline_record/322"
140+
(let
141+
(A =
142+
(makeblock 248 "Extension_with_inline_record.A" (caml_fresh_oo_id 0))
143+
test =
144+
(function param : int
145+
(if (== (field_imm 0 param) A) (atomic_load param 1) 0))
146+
*match* =
147+
(if (== (apply test (makemutable 0 (*,int) A 42)) 42) 0
148+
(raise (makeblock 0 (global Assert_failure!) [0: "" 11 11]))))
149+
(makeblock 0 A test)))
150+
module Extension_with_inline_record :
151+
sig
152+
type t = ..
153+
type t += A of { mutable x : int [@atomic]; }
154+
val test : t -> int
155+
end
156+
|}];;
157+
158+
159+
(* Marking a field [@atomic] in a float-only record disables the unboxing optimization. *)
160+
module Float_records = struct
161+
type t = { x : float; mutable y : float [@atomic] }
162+
163+
(* one should see in the -dlambda output below that this creates a block of tag 0. *)
164+
let mk_t x y : t = { x; y }
165+
let get v = v.y
166+
end
167+
[%%expect{|
168+
(apply (field_mut 1 (global Toploop!)) "Float_records/337"
169+
(let
170+
(mk_t = (function x[float] y[float] (makemutable 0 (float,float) x y))
171+
get = (function v : float (atomic_load v 1)))
172+
(makeblock 0 mk_t get)))
173+
module Float_records :
174+
sig
175+
type t = { x : float; mutable y : float [@atomic]; }
176+
val mk_t : float -> float -> t
177+
val get : t -> float
178+
end
179+
|}];;
180+
181+

0 commit comments

Comments
 (0)