-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPrimOp-Exception.dl
92 lines (84 loc) · 3.16 KB
/
PrimOp-Exception.dl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*
HINT: is interpreted -/+
primop effectful
+ "catch#" :: ({"State#" {RealWorld}} -> {"GHC.Prim.Unit#" %a}) -> (%b -> {"State#" {RealWorld}} -> {"GHC.Prim.Unit#" %a}) -> {"State#" {RealWorld}} -> {"GHC.Prim.Unit#" %a}
+ "raise#" :: %b -> %o
+ "raiseIO#" :: %a -> {"State#" {RealWorld}} -> {"GHC.Prim.Unit#" %b}
+ "maskAsyncExceptions#" :: ({"State#" {RealWorld}} -> {"GHC.Prim.Unit#" %a}) -> {"State#" {RealWorld}} -> {"GHC.Prim.Unit#" %a}
+ "maskUninterruptible#" :: ({"State#" {RealWorld}} -> {"GHC.Prim.Unit#" %a}) -> {"State#" {RealWorld}} -> {"GHC.Prim.Unit#" %a}
+ "unmaskAsyncExceptions#" :: ({"State#" {RealWorld}} -> {"GHC.Prim.Unit#" %a}) -> {"State#" {RealWorld}} -> {"GHC.Prim.Unit#" %a}
- "getMaskingState#" :: {"State#" {RealWorld}} -> {"GHC.Prim.Unit#" T_Int64}
*/
/*
NOTES for higher order primop support:
the higher order primops execute function calls and also pass the arguments
this mean that they have to collect the arguments somewhere, maybe from an accompaning other primop provides it,
i.e. raise provides the arguments for catch
*/
// SECTION: higher order primop evaluator
.decl RaisedEx(f:Variable) brie
.output RaisedEx
// "raise#" :: %b -> %o
// "raiseIO#" :: %a -> {"State#" {RealWorld}} -> {"GHC.Prim.Unit#" %b}
// collect raised exceptions
USED("PrimOp-Exception-01")
//Called(r, op),
RaisedEx(ex) :-
( op = "raise#"
; op = "raiseIO#"
),
Call(r, op, _),
CallArgument(r, 0, ex),
NEW_REACHABLE(r)
.
// CHECKED
// "catch#" :: ({"State#" {RealWorld}} -> {"GHC.Prim.Unit#" %a})
// -> (%b -> {"State#" {RealWorld}} -> {"GHC.Prim.Unit#" %a})
// -> {"State#" {RealWorld}}
// -> {"GHC.Prim.Unit#" %a}
// handle the wrapped function
USED("PrimOp-Exception-02")
//Called(r, op),
CallPNode1("catch#-wrapped", r, v0, v2_state) :-
op = "catch#",
Call(r, op, _),
// wrapped fun
CallArgument(r, 0, v0),
// state
CallArgument(r, 2, v2_state),
NEW_REACHABLE(r)
.
// CHECKED
// NOTE: the handler has its own rule, because it fires only when there are exceptions, while the wrapped function is always called
// handle ex-handler
USED("PrimOp-Exception-03")
//Called(r, op),
CallPNode2("catch#-handler", r, v1, ex, v2_state) :-
op = "catch#",
Call(r, op, _),
// handler
CallArgument(r, 1, v1),
// state
CallArgument(r, 2, v2_state),
// exceptions
RaisedEx(ex),
NEW_REACHABLE(r)
.
// CHECKED
// "maskAsyncExceptions#" :: ({"State#" {RealWorld}} -> {"GHC.Prim.Unit#" %a}) -> {"State#" {RealWorld}} -> {"GHC.Prim.Unit#" %a}
// "maskUninterruptible#" :: ({"State#" {RealWorld}} -> {"GHC.Prim.Unit#" %a}) -> {"State#" {RealWorld}} -> {"GHC.Prim.Unit#" %a}
// "unmaskAsyncExceptions#" :: ({"State#" {RealWorld}} -> {"GHC.Prim.Unit#" %a}) -> {"State#" {RealWorld}} -> {"GHC.Prim.Unit#" %a}
USED("PrimOp-Exception-04")
//Called(r, op),
CallPNode1("mask", r, v0, v1_state) :-
( op = "maskAsyncExceptions#"
; op = "maskUninterruptible#"
; op = "unmaskAsyncExceptions#"
),
Call(r, op, _),
// pass argument to the wrapped function
CallArgument(r, 0, v0),
CallArgument(r, 1, v1_state),
NEW_REACHABLE(r)
.
// CHECKED