File tree 4 files changed +41
-8
lines changed
middle_end/flambda2/to_cmm
4 files changed +41
-8
lines changed Original file line number Diff line number Diff line change @@ -412,7 +412,13 @@ let can_raise_terminator (i : terminator) =
412
412
| Raise _ | Tailcall_func _ | Call _ | Prim { op = Probe _; label_after = _ }
413
413
->
414
414
true
415
- | Prim { op = External { alloc; _ } ; label_after = _ } -> alloc
415
+ | Prim { op = External { alloc; effects; _ } ; label_after = _ } -> (
416
+ if not alloc
417
+ then false
418
+ else
419
+ (* Even if going via [caml_c_call], if there are no effects, the function
420
+ cannot raise an exception. (Example: [caml_obj_dup].) *)
421
+ match effects with No_effects -> false | Arbitrary_effects -> true )
416
422
| Specific_can_raise { op; _ } ->
417
423
assert (Arch. operation_can_raise op);
418
424
true
Original file line number Diff line number Diff line change @@ -858,8 +858,8 @@ let unary_primitive env res dbg f arg =
858
858
( None ,
859
859
res,
860
860
C. extcall ~dbg ~alloc: true ~returns: true ~is_c_builtin: false
861
- ~effects: Arbitrary_effects ~coeffects: Has_coeffects ~ty_args: []
862
- " caml_obj_dup " Cmm. typ_val [arg] )
861
+ ~effects: No_effects ~coeffects: Has_coeffects ~ty_args: [] " caml_obj_dup "
862
+ Cmm. typ_val [arg] )
863
863
| Is_int _ -> None , res, C. and_int arg (C. int ~dbg 1 ) dbg
864
864
| Is_null -> None , res, C. eq ~dbg arg (C. nativeint ~dbg 0n )
865
865
| Get_tag -> None , res, C. get_tag arg dbg
Original file line number Diff line number Diff line change @@ -154,15 +154,22 @@ CAMLprim value caml_obj_with_tag(value new_tag_v, value arg)
154
154
tag_t tag_for_alloc ;
155
155
uintnat infix_offset = 0 ;
156
156
157
+ // This function must not raise exceptions (except asynchronous exceptions).
158
+ // It behaves just like an allocation function, which has generative effects,
159
+ // but not arbitrary effects. (See the [Obj_dup] case in [To_cmm].)
160
+
157
161
tag_t new_tag = (tag_t )Long_val (new_tag_v );
162
+ #ifdef DEBUG
158
163
tag_t existing_tag = Tag_val (arg );
164
+ #endif
159
165
160
- if ((existing_tag == Closure_tag || existing_tag == Infix_tag
166
+ CAMLassert (
167
+ !(
168
+ (existing_tag == Closure_tag || existing_tag == Infix_tag
161
169
|| new_tag == Closure_tag || new_tag == Infix_tag )
162
- && existing_tag != new_tag ) {
163
- caml_failwith ("Cannot change tags of existing closures or create \
164
- new closures using [caml_obj_with_tag]" );
165
- }
170
+ && existing_tag != new_tag ));
171
+ // Cannot change tags of existing closures or create new closures using
172
+ // [caml_obj_with_tag].
166
173
167
174
if (new_tag == Infix_tag ) {
168
175
// If we received an infix block, we must return the same; but the whole
Original file line number Diff line number Diff line change
1
+ (* TEST *)
2
+
3
+ [@@@ ocaml.flambda_o3]
4
+
5
+ let [@ inline never] bar _ _ = ()
6
+
7
+ let [@ inline never] baz () = ()
8
+
9
+ let foo size (x : int ) arr y =
10
+ let extra_arg_array = ref arr in
11
+ let extra_arg_int = ref 0 in
12
+ (try
13
+ for i = 0 to size - 1 do
14
+ if i > 20 then (
15
+ let _ = Sys. opaque_identity (Obj. dup y) in
16
+ baz ()
17
+ )
18
+ done
19
+ with _exn -> () );
20
+ bar ! extra_arg_array ! extra_arg_int
You can’t perform that action at this time.
0 commit comments