@effekt-lang/effekt 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +36 -0
- package/bin/effekt +0 -0
- package/bin/effekt.sh +2 -0
- package/libraries/chez/THIRD-PARTY.txt +11 -0
- package/libraries/chez/callcc/datatype.ss +188 -0
- package/libraries/chez/callcc/effekt.effekt +221 -0
- package/libraries/chez/callcc/effekt.ss +31 -0
- package/libraries/chez/callcc/seq.ss +44 -0
- package/libraries/chez/callcc/seq0.ss +69 -0
- package/libraries/chez/callcc/tail.ss +76 -0
- package/libraries/chez/callcc/tail0.ss +89 -0
- package/libraries/chez/common/effekt_matching.ss +100 -0
- package/libraries/chez/common/effekt_primitives.ss +97 -0
- package/libraries/chez/common/immutable/cslist.effekt +31 -0
- package/libraries/chez/common/immutable/dequeue.effekt +78 -0
- package/libraries/chez/common/immutable/list.effekt +643 -0
- package/libraries/chez/common/immutable/option.effekt +39 -0
- package/libraries/chez/common/immutable/result.effekt +29 -0
- package/libraries/chez/common/io/args.effekt +20 -0
- package/libraries/chez/common/mutable/array.effekt +27 -0
- package/libraries/chez/common/mutable/dict.effekt +30 -0
- package/libraries/chez/common/mutable/heap.effekt +12 -0
- package/libraries/chez/common/test.effekt +59 -0
- package/libraries/chez/common/text/pregexp.scm +772 -0
- package/libraries/chez/common/text/regex.effekt +33 -0
- package/libraries/chez/common/text/string.effekt +46 -0
- package/libraries/chez/lift/effekt.effekt +217 -0
- package/libraries/chez/lift/effekt.ss +118 -0
- package/libraries/chez/monadic/effekt.effekt +218 -0
- package/libraries/chez/monadic/effekt.ss +84 -0
- package/libraries/chez/monadic/seq0.ss +76 -0
- package/libraries/js/effekt.effekt +284 -0
- package/libraries/js/effekt_builtins.js +26 -0
- package/libraries/js/effekt_matching.js +79 -0
- package/libraries/js/effekt_runtime.js +385 -0
- package/libraries/js/immutable/dequeue.effekt +78 -0
- package/libraries/js/immutable/list.effekt +643 -0
- package/libraries/js/immutable/option.effekt +49 -0
- package/libraries/js/immutable/result.effekt +29 -0
- package/libraries/js/io/args.effekt +9 -0
- package/libraries/js/io/async.effekt +28 -0
- package/libraries/js/io/async.js +2 -0
- package/libraries/js/io/file.effekt +50 -0
- package/libraries/js/io/file_include.js +13 -0
- package/libraries/js/mutable/array.effekt +98 -0
- package/libraries/js/mutable/heap.effekt +32 -0
- package/libraries/js/mutable/map.effekt +32 -0
- package/libraries/js/test.effekt +59 -0
- package/libraries/js/text/regex.effekt +34 -0
- package/libraries/js/text/string.effekt +64 -0
- package/libraries/js/unsafe/cont.effekt +11 -0
- package/libraries/js/web/dom.effekt +45 -0
- package/libraries/llvm/buffer.c +181 -0
- package/libraries/llvm/effekt.effekt +243 -0
- package/libraries/llvm/forward-declare-c.ll +24 -0
- package/libraries/llvm/hole.c +11 -0
- package/libraries/llvm/immutable/list.effekt +678 -0
- package/libraries/llvm/immutable/option.effekt +53 -0
- package/libraries/llvm/immutable/result.effekt +29 -0
- package/libraries/llvm/io/args.effekt +24 -0
- package/libraries/llvm/io.c +24 -0
- package/libraries/llvm/main.c +39 -0
- package/libraries/llvm/rts.ll +619 -0
- package/libraries/llvm/sanity.c +16 -0
- package/libraries/llvm/text/string.effekt +179 -0
- package/libraries/llvm/types.c +20 -0
- package/libraries/ml/effekt.effekt +267 -0
- package/libraries/ml/effekt.sml +63 -0
- package/libraries/ml/immutable/dequeue.effekt +81 -0
- package/libraries/ml/immutable/list.effekt +674 -0
- package/libraries/ml/immutable/option.effekt +53 -0
- package/libraries/ml/immutable/result.effekt +29 -0
- package/libraries/ml/immutable/seq.effekt +903 -0
- package/libraries/ml/internal/option.effekt +18 -0
- package/libraries/ml/io/args.effekt +41 -0
- package/libraries/ml/mutable/array.effekt +43 -0
- package/libraries/ml/random.effekt +85 -0
- package/libraries/ml/test.effekt +60 -0
- package/libraries/ml/text/regex.effekt +107 -0
- package/libraries/ml/text/string.effekt +81 -0
- package/licenses/THIRD-PARTY.txt +21 -0
- package/licenses/apache-2.0 - license-2.0.txt +202 -0
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +61 -0
- package/licenses/kiama-license.txt +373 -0
- package/licenses/kiama-readme.txt +186 -0
- package/licenses/mit license - mit-license.html +769 -0
- package/licenses/the apache software license, version 2.0 - license-2.0.txt +202 -0
- package/licenses/the bsd license - bsd-license.html +762 -0
- package/licenses/the mit license - mit.html +769 -0
- package/package.json +26 -18
|
@@ -0,0 +1,619 @@
|
|
|
1
|
+
; Run-Time System
|
|
2
|
+
|
|
3
|
+
; Basic types
|
|
4
|
+
|
|
5
|
+
%Env = type ptr
|
|
6
|
+
|
|
7
|
+
; Reference counts
|
|
8
|
+
%Rc = type i64
|
|
9
|
+
|
|
10
|
+
; Code to share (bump rc) an environment
|
|
11
|
+
%Sharer = type ptr
|
|
12
|
+
|
|
13
|
+
; Code to drop an environment
|
|
14
|
+
%Eraser = type ptr
|
|
15
|
+
|
|
16
|
+
; Every heap object starts with a header
|
|
17
|
+
%Header = type {%Rc, %Eraser}
|
|
18
|
+
|
|
19
|
+
; A heap object is a pointer to a header followed by payload.
|
|
20
|
+
;
|
|
21
|
+
; +--[ Header ]--+-------------+
|
|
22
|
+
; | Rc | Eraser | Payload ... |
|
|
23
|
+
; +--------------+-------------+
|
|
24
|
+
%Obj = type ptr
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
; A Frame has the following layout
|
|
28
|
+
;
|
|
29
|
+
; +-------[ FrameHeader ]-----+--------------+
|
|
30
|
+
; | RetAdr | Sharer | Eraser | Payload ... |
|
|
31
|
+
; +---------------------------+--------------+
|
|
32
|
+
|
|
33
|
+
; A stack pointer points to the top-most frame followed by all other frames.
|
|
34
|
+
;
|
|
35
|
+
; For example
|
|
36
|
+
;
|
|
37
|
+
; +--------------------+ <- Limit
|
|
38
|
+
; : :
|
|
39
|
+
; : : <- Sp
|
|
40
|
+
; +--------------------+
|
|
41
|
+
; | FrameHeader |
|
|
42
|
+
; | z |
|
|
43
|
+
; | y |
|
|
44
|
+
; | x |
|
|
45
|
+
; +--------------------+
|
|
46
|
+
; | ... next frame ... |
|
|
47
|
+
; +--------------------+
|
|
48
|
+
; : ... :
|
|
49
|
+
; +--------------------+ <- Base
|
|
50
|
+
%Sp = type ptr
|
|
51
|
+
%Base = type %Sp
|
|
52
|
+
%Limit = type %Sp
|
|
53
|
+
%RetAdr = type ptr
|
|
54
|
+
%FrameHeader = type { %RetAdr, %Sharer, %Eraser }
|
|
55
|
+
|
|
56
|
+
; Pointers for a heap allocated stack
|
|
57
|
+
%Mem = type { %Sp, %Base, %Limit }
|
|
58
|
+
|
|
59
|
+
; The garbage collector differentiates three groups of types:
|
|
60
|
+
; - Values (Integer, Double)
|
|
61
|
+
; - Objects (Positive, Negative)
|
|
62
|
+
; - Strings
|
|
63
|
+
; For each group we have an arena where mutable state is allocated.
|
|
64
|
+
;
|
|
65
|
+
%Region = type [ 3 x %Mem ]
|
|
66
|
+
|
|
67
|
+
; The "meta" stack (a stack of stacks)
|
|
68
|
+
%Stk = type ptr
|
|
69
|
+
|
|
70
|
+
; This is used for two purposes:
|
|
71
|
+
; - a refied first-class list of stacks (cyclic linked-list)
|
|
72
|
+
; - as part of an intrusive linked-list of stacks (meta stack)
|
|
73
|
+
%StkVal = type { %Rc, %Mem, %Region, %Stk }
|
|
74
|
+
|
|
75
|
+
; Positive data types consist of a (type-local) tag and a heap object
|
|
76
|
+
%Pos = type {i64, %Obj}
|
|
77
|
+
%Boolean = type %Pos
|
|
78
|
+
%Unit = type %Pos
|
|
79
|
+
|
|
80
|
+
; Negative types (codata) consist of a vtable and a heap object
|
|
81
|
+
%Neg = type {ptr, %Obj}
|
|
82
|
+
|
|
83
|
+
; Offset within the arena
|
|
84
|
+
%Ref = type i64
|
|
85
|
+
|
|
86
|
+
; Global locations
|
|
87
|
+
|
|
88
|
+
@base = private global %Base null
|
|
89
|
+
@limit = private global %Limit null
|
|
90
|
+
@region = private global %Region zeroinitializer
|
|
91
|
+
@rest = private global %Stk undef
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
define %StkVal @getStk(%Sp %sp) alwaysinline {
|
|
95
|
+
%base = load %Base, ptr @base
|
|
96
|
+
%limit = load %Limit, ptr @limit
|
|
97
|
+
%region = load %Region, ptr @region
|
|
98
|
+
%rest = load %Stk, ptr @rest
|
|
99
|
+
|
|
100
|
+
%stk.0 = insertvalue %StkVal undef, %Rc 0, 0
|
|
101
|
+
%stk.1 = insertvalue %StkVal %stk.0, %Sp %sp, 1, 0
|
|
102
|
+
%stk.2 = insertvalue %StkVal %stk.1, %Base %base, 1, 1
|
|
103
|
+
%stk.3 = insertvalue %StkVal %stk.2, %Limit %limit, 1, 2
|
|
104
|
+
%stk.4 = insertvalue %StkVal %stk.3, %Region %region, 2
|
|
105
|
+
%stk.5 = insertvalue %StkVal %stk.4, %Stk %rest, 3
|
|
106
|
+
|
|
107
|
+
ret %StkVal %stk.5
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
define void @setStk(%StkVal %stk) alwaysinline {
|
|
111
|
+
%base = extractvalue %StkVal %stk, 1, 1
|
|
112
|
+
%limit = extractvalue %StkVal %stk, 1, 2
|
|
113
|
+
%region = extractvalue %StkVal %stk, 2
|
|
114
|
+
%rest = extractvalue %StkVal %stk, 3
|
|
115
|
+
|
|
116
|
+
store %Base %base, ptr @base
|
|
117
|
+
store %Limit %limit, ptr @limit
|
|
118
|
+
store %Region %region, ptr @region
|
|
119
|
+
store %Stk %rest, ptr @rest
|
|
120
|
+
ret void
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
; Foreign imports
|
|
124
|
+
|
|
125
|
+
declare ptr @malloc(i64)
|
|
126
|
+
declare void @free(ptr)
|
|
127
|
+
declare ptr @realloc(ptr, i64)
|
|
128
|
+
declare void @memcpy(ptr, ptr, i64)
|
|
129
|
+
declare i64 @llvm.ctlz.i64 (i64 , i1)
|
|
130
|
+
declare i64 @llvm.fshr.i64(i64, i64, i64)
|
|
131
|
+
declare void @print(i64)
|
|
132
|
+
declare void @exit(i64)
|
|
133
|
+
|
|
134
|
+
; Garbage collection
|
|
135
|
+
|
|
136
|
+
define %Obj @newObject(%Eraser %eraser, i64 %envsize) alwaysinline {
|
|
137
|
+
; This magical 16 is the size of the object header
|
|
138
|
+
%size = add i64 %envsize, 16
|
|
139
|
+
%obj = call ptr @malloc(i64 %size)
|
|
140
|
+
%objrc = getelementptr %Header, ptr %obj, i64 0, i32 0
|
|
141
|
+
%objeraser = getelementptr %Header, ptr %obj, i64 0, i32 1
|
|
142
|
+
store %Rc 0, ptr %objrc
|
|
143
|
+
store %Eraser %eraser, ptr %objeraser
|
|
144
|
+
ret %Obj %obj
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
define %Env @objectEnvironment(%Obj %obj) alwaysinline {
|
|
148
|
+
; Environment is stored right after header
|
|
149
|
+
%env = getelementptr %Header, ptr %obj, i64 1
|
|
150
|
+
ret %Env %env
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
define void @shareObject(%Obj %obj) alwaysinline {
|
|
154
|
+
%isnull = icmp eq %Obj %obj, null
|
|
155
|
+
br i1 %isnull, label %done, label %next
|
|
156
|
+
|
|
157
|
+
next:
|
|
158
|
+
%objrc = getelementptr %Header, ptr %obj, i64 0, i32 0
|
|
159
|
+
%rc = load %Rc, ptr %objrc
|
|
160
|
+
%rc.1 = add %Rc %rc, 1
|
|
161
|
+
store %Rc %rc.1, ptr %objrc
|
|
162
|
+
br label %done
|
|
163
|
+
|
|
164
|
+
done:
|
|
165
|
+
ret void
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
define void @sharePositive(%Pos %val) alwaysinline {
|
|
169
|
+
%obj = extractvalue %Pos %val, 1
|
|
170
|
+
tail call void @shareObject(%Obj %obj)
|
|
171
|
+
ret void
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
define void @shareNegative(%Neg %val) alwaysinline {
|
|
175
|
+
%obj = extractvalue %Neg %val, 1
|
|
176
|
+
tail call void @shareObject(%Obj %obj)
|
|
177
|
+
ret void
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
define void @eraseObject(%Obj %obj) alwaysinline {
|
|
181
|
+
%isnull = icmp eq %Obj %obj, null
|
|
182
|
+
br i1 %isnull, label %done, label %next
|
|
183
|
+
|
|
184
|
+
next:
|
|
185
|
+
%objrc = getelementptr %Header, ptr %obj, i64 0, i32 0
|
|
186
|
+
%rc = load %Rc, ptr %objrc
|
|
187
|
+
switch %Rc %rc, label %decr [%Rc 0, label %free]
|
|
188
|
+
|
|
189
|
+
decr:
|
|
190
|
+
%rc.1 = sub %Rc %rc, 1
|
|
191
|
+
store %Rc %rc.1, ptr %objrc
|
|
192
|
+
ret void
|
|
193
|
+
|
|
194
|
+
free:
|
|
195
|
+
%objeraser = getelementptr %Header, ptr %obj, i64 0, i32 1
|
|
196
|
+
%eraser = load %Eraser, ptr %objeraser
|
|
197
|
+
%env = call %Env @objectEnvironment(%Obj %obj)
|
|
198
|
+
call fastcc void %eraser(%Env %env)
|
|
199
|
+
call void @free(%Obj %obj)
|
|
200
|
+
br label %done
|
|
201
|
+
|
|
202
|
+
done:
|
|
203
|
+
ret void
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
define void @erasePositive(%Pos %val) alwaysinline {
|
|
207
|
+
%obj = extractvalue %Pos %val, 1
|
|
208
|
+
tail call void @eraseObject(%Obj %obj)
|
|
209
|
+
ret void
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
define void @eraseNegative(%Neg %val) alwaysinline {
|
|
213
|
+
%obj = extractvalue %Neg %val, 1
|
|
214
|
+
tail call void @eraseObject(%Obj %obj)
|
|
215
|
+
ret void
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
; Arena management
|
|
220
|
+
define ptr @getRegionPointer(i64 %evidence) alwaysinline {
|
|
221
|
+
entry:
|
|
222
|
+
switch i64 %evidence, label %loop [i64 0, label %here]
|
|
223
|
+
|
|
224
|
+
here:
|
|
225
|
+
ret ptr @region
|
|
226
|
+
|
|
227
|
+
loop:
|
|
228
|
+
%stkp = phi ptr [@rest, %entry], [%nextp, %loop]
|
|
229
|
+
%i = phi i64 [%evidence, %entry], [%nexti, %loop]
|
|
230
|
+
%stk = load %Stk, ptr %stkp
|
|
231
|
+
%regionp = getelementptr %StkVal, %Stk %stk, i64 0, i32 2
|
|
232
|
+
%nextp = getelementptr %StkVal, %Stk %stk, i64 0, i32 3
|
|
233
|
+
%nexti = sub i64 %i, 1
|
|
234
|
+
%cmp = icmp eq i64 %nexti, 0
|
|
235
|
+
|
|
236
|
+
br i1 %cmp, label %done, label %loop
|
|
237
|
+
|
|
238
|
+
done:
|
|
239
|
+
ret ptr %regionp
|
|
240
|
+
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
define { ptr, %Ref } @alloc(i64 %idx, i64 %evidence) alwaysinline {
|
|
246
|
+
%regionp = call ptr @getRegionPointer(i64 %evidence)
|
|
247
|
+
%spp = getelementptr %Region, ptr %regionp, i64 0, i64 %idx, i32 0
|
|
248
|
+
%basep = getelementptr %Region, ptr %regionp, i64 0, i64 %idx, i32 1
|
|
249
|
+
%limitp = getelementptr %Region, ptr %regionp, i64 0, i64 %idx, i32 2
|
|
250
|
+
|
|
251
|
+
%sp = load %Sp, ptr %spp
|
|
252
|
+
%base = load %Base, ptr %basep
|
|
253
|
+
%limit = load %Limit, ptr %limitp
|
|
254
|
+
|
|
255
|
+
%obj = icmp ne i64 %idx, 0
|
|
256
|
+
%size = select i1 %obj, i64 16, i64 8
|
|
257
|
+
|
|
258
|
+
%nextsp = getelementptr i8, %Sp %sp, i64 %size
|
|
259
|
+
|
|
260
|
+
%cmp = icmp ule %Sp %nextsp, %limit
|
|
261
|
+
br i1 %cmp, label %continue, label %realloc
|
|
262
|
+
|
|
263
|
+
continue:
|
|
264
|
+
store %Sp %nextsp, ptr %spp
|
|
265
|
+
%intb = ptrtoint %Base %base to i64
|
|
266
|
+
%intsp = ptrtoint %Sp %sp to i64
|
|
267
|
+
%offset = sub i64 %intsp, %intb
|
|
268
|
+
|
|
269
|
+
%ret.0 = insertvalue { ptr, %Ref } undef, %Sp %sp, 0
|
|
270
|
+
%ret.1 = insertvalue { ptr, %Ref } %ret.0, %Ref %offset, 1
|
|
271
|
+
ret { ptr, %Ref } %ret.1
|
|
272
|
+
|
|
273
|
+
realloc:
|
|
274
|
+
%intbase = ptrtoint %Base %base to i64
|
|
275
|
+
%intlimit = ptrtoint %Limit %limit to i64
|
|
276
|
+
%arenasize = sub i64 %intlimit, %intbase
|
|
277
|
+
%empty = icmp eq i64 %arenasize, 0
|
|
278
|
+
%double = mul i64 %arenasize, 2
|
|
279
|
+
%newarenasize = select i1 %empty, i64 1024, i64 %double
|
|
280
|
+
|
|
281
|
+
%newbase = call ptr @realloc(ptr %base, i64 %newarenasize)
|
|
282
|
+
%newlimit = getelementptr i8, %Base %newbase, i64 %newarenasize
|
|
283
|
+
%newsp = getelementptr i8, %Base %newbase, i64 %arenasize
|
|
284
|
+
%newnextsp = getelementptr i8, %Sp %newsp, i64 %size
|
|
285
|
+
|
|
286
|
+
store %Base %newbase, ptr %basep
|
|
287
|
+
store %Limit %newlimit, ptr %limitp
|
|
288
|
+
store %Sp %newnextsp, ptr %spp
|
|
289
|
+
|
|
290
|
+
%ret..0 = insertvalue { ptr, %Ref } undef, %Sp %newsp, 0
|
|
291
|
+
%ret..1 = insertvalue { ptr, %Ref } %ret..0, %Ref %arenasize, 1
|
|
292
|
+
ret { ptr, %Ref } %ret..1
|
|
293
|
+
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
define ptr @getPtr(%Ref %ref, i64 %idx, i64 %evidence) alwaysinline {
|
|
297
|
+
%regionp = call ptr @getRegionPointer(i64 %evidence)
|
|
298
|
+
%basep = getelementptr %Region, ptr %regionp, i64 0, i64 %idx, i32 1
|
|
299
|
+
%base = load %Base, ptr %basep
|
|
300
|
+
%ptr = getelementptr i8, ptr %base, %Ref %ref
|
|
301
|
+
ret ptr %ptr
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
; Meta-stack management
|
|
305
|
+
|
|
306
|
+
define %Mem @newMem() alwaysinline {
|
|
307
|
+
%sp = call %Sp @malloc(i64 1024)
|
|
308
|
+
%limit = getelementptr i8, ptr %sp, i64 1024
|
|
309
|
+
|
|
310
|
+
%mem.0 = insertvalue %Mem undef, %Sp %sp, 0
|
|
311
|
+
%mem.1 = insertvalue %Mem %mem.0, %Base %sp, 1
|
|
312
|
+
%mem.2 = insertvalue %Mem %mem.1, %Limit %limit, 2
|
|
313
|
+
|
|
314
|
+
ret %Mem %mem.2
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
define %Stk @newStack() alwaysinline {
|
|
318
|
+
|
|
319
|
+
; TODO find actual size of stack
|
|
320
|
+
%stk = call ptr @malloc(i64 112)
|
|
321
|
+
|
|
322
|
+
; TODO initialize to zero and grow later
|
|
323
|
+
%stackmem = call %Mem @newMem()
|
|
324
|
+
|
|
325
|
+
%stk.0 = insertvalue %StkVal undef, %Rc 0, 0
|
|
326
|
+
%stk.1 = insertvalue %StkVal %stk.0, %Mem %stackmem, 1
|
|
327
|
+
%stk.2 = insertvalue %StkVal %stk.1, %Region zeroinitializer, 2
|
|
328
|
+
%stk.3 = insertvalue %StkVal %stk.2, %Stk %stk, 3
|
|
329
|
+
|
|
330
|
+
store %StkVal %stk.3, %Stk %stk
|
|
331
|
+
|
|
332
|
+
ret %Stk %stk
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
define %Sp @pushStack(%Stk %stk, %Sp %oldsp) alwaysinline {
|
|
336
|
+
%newstk = load %StkVal, %Stk %stk
|
|
337
|
+
|
|
338
|
+
%oldstk = call %StkVal @getStk(%Sp %oldsp)
|
|
339
|
+
|
|
340
|
+
call void @setStk(%StkVal %newstk)
|
|
341
|
+
|
|
342
|
+
store %StkVal %oldstk, %Stk %stk
|
|
343
|
+
|
|
344
|
+
%newsp = extractvalue %StkVal %newstk, 1, 0
|
|
345
|
+
ret %Sp %newsp
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
; pop n+1 stacks
|
|
349
|
+
define {%Stk, %Sp} @popStacks(%Sp %oldsp, i64 %n) alwaysinline {
|
|
350
|
+
entry:
|
|
351
|
+
%oldstk = call %StkVal @getStk(%Sp %oldsp)
|
|
352
|
+
br label %loop
|
|
353
|
+
|
|
354
|
+
loop:
|
|
355
|
+
%stkval = phi %StkVal [%oldstk, %entry], [%newstk, %loop]
|
|
356
|
+
%i = phi i64 [%n, %entry], [%nexti, %loop]
|
|
357
|
+
|
|
358
|
+
%newstkp = extractvalue %StkVal %stkval, 3
|
|
359
|
+
%newstk = load %StkVal, %Stk %newstkp
|
|
360
|
+
|
|
361
|
+
%nexti = sub i64 %i, 1
|
|
362
|
+
|
|
363
|
+
%cmp = icmp eq i64 %i, 0
|
|
364
|
+
br i1 %cmp, label %done, label %loop
|
|
365
|
+
|
|
366
|
+
done:
|
|
367
|
+
call void @setStk(%StkVal %newstk)
|
|
368
|
+
|
|
369
|
+
store %StkVal %oldstk, %Stk %newstkp
|
|
370
|
+
|
|
371
|
+
%newsp = extractvalue %StkVal %newstk, 1, 0
|
|
372
|
+
%ret.0 = insertvalue {%Stk, %Sp} undef, %Stk %newstkp, 0
|
|
373
|
+
%ret.1 = insertvalue {%Stk, %Sp} %ret.0, %Sp %newsp, 1
|
|
374
|
+
|
|
375
|
+
ret {%Stk, %Sp} %ret.1
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
define %Sp @underflowStack(%Sp %sp) alwaysinline {
|
|
379
|
+
%stk = load %Stk, ptr @rest
|
|
380
|
+
%newstk = load %StkVal, %Stk %stk
|
|
381
|
+
|
|
382
|
+
%region = load %Region, ptr @region
|
|
383
|
+
call void @eraseRegion(%Region %region)
|
|
384
|
+
|
|
385
|
+
call void @setStk(%StkVal %newstk)
|
|
386
|
+
|
|
387
|
+
call void @free(%Sp %sp)
|
|
388
|
+
call void @free(%Stk %stk)
|
|
389
|
+
|
|
390
|
+
%newsp = extractvalue %StkVal %newstk, 1, 0
|
|
391
|
+
ret %Sp %newsp
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
define %Mem @copyMem(%Mem %mem) alwaysinline {
|
|
395
|
+
%sp = extractvalue %Mem %mem, 0
|
|
396
|
+
%base = extractvalue %Mem %mem, 1
|
|
397
|
+
%limit = extractvalue %Mem %mem, 2
|
|
398
|
+
|
|
399
|
+
%intsp = ptrtoint %Sp %sp to i64
|
|
400
|
+
%intbase = ptrtoint %Base %base to i64
|
|
401
|
+
%intlimit = ptrtoint %Limit %limit to i64
|
|
402
|
+
%used = sub i64 %intsp, %intbase
|
|
403
|
+
%size = sub i64 %intlimit, %intbase
|
|
404
|
+
|
|
405
|
+
%newbase = call ptr @malloc(i64 %size)
|
|
406
|
+
%intnewbase = ptrtoint %Base %newbase to i64
|
|
407
|
+
%intnewsp = add i64 %intnewbase, %used
|
|
408
|
+
%intnewlimit = add i64 %intnewbase, %size
|
|
409
|
+
%newsp = inttoptr i64 %intnewsp to %Sp
|
|
410
|
+
%newlimit = inttoptr i64 %intnewlimit to %Limit
|
|
411
|
+
|
|
412
|
+
call void @memcpy(ptr %newbase, ptr %base, i64 %used)
|
|
413
|
+
|
|
414
|
+
%mem.0 = insertvalue %Mem undef, %Sp %newsp, 0
|
|
415
|
+
%mem.1 = insertvalue %Mem %mem.0, %Base %newbase, 1
|
|
416
|
+
%mem.2 = insertvalue %Mem %mem.1, %Limit %newlimit, 2
|
|
417
|
+
|
|
418
|
+
ret %Mem %mem.2
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
define %Region @copyRegion(%Region %region) alwaysinline {
|
|
422
|
+
%mem.0 = extractvalue %Region %region, 0
|
|
423
|
+
%mem.1 = extractvalue %Region %region, 1
|
|
424
|
+
%mem.2 = extractvalue %Region %region, 2
|
|
425
|
+
|
|
426
|
+
%objectsbase = extractvalue %Region %region, 1, 1
|
|
427
|
+
%objectssp = extractvalue %Region %region, 1, 0
|
|
428
|
+
call void @forEachObject(%Base %objectsbase, %Sp %objectssp, %Eraser @sharePositive)
|
|
429
|
+
|
|
430
|
+
%stringsbase = extractvalue %Region %region, 2, 1
|
|
431
|
+
%stringssp = extractvalue %Region %region, 2, 0
|
|
432
|
+
call void @forEachObject(%Base %stringsbase, %Sp %stringssp, %Eraser @c_buffer_refcount_increment)
|
|
433
|
+
|
|
434
|
+
%newmem.0 = call %Mem @copyMem(%Mem %mem.0)
|
|
435
|
+
%newmem.1 = call %Mem @copyMem(%Mem %mem.1)
|
|
436
|
+
%newmem.2 = call %Mem @copyMem(%Mem %mem.2)
|
|
437
|
+
|
|
438
|
+
%region.0 = insertvalue %Region undef, %Mem %newmem.0, 0
|
|
439
|
+
%region.1 = insertvalue %Region %region.0, %Mem %newmem.1, 1
|
|
440
|
+
%region.2 = insertvalue %Region %region.1, %Mem %newmem.2, 2
|
|
441
|
+
|
|
442
|
+
ret %Region %region.2
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
define %Stk @uniqueStack(%Stk %stk) alwaysinline {
|
|
446
|
+
|
|
447
|
+
entry:
|
|
448
|
+
%stkrc = getelementptr %StkVal, %Stk %stk, i64 0, i32 0
|
|
449
|
+
%rc = load %Rc, ptr %stkrc
|
|
450
|
+
switch %Rc %rc, label %copy [%Rc 0, label %done]
|
|
451
|
+
|
|
452
|
+
done:
|
|
453
|
+
ret %Stk %stk
|
|
454
|
+
|
|
455
|
+
copy:
|
|
456
|
+
%newoldrc = sub %Rc %rc, 1
|
|
457
|
+
store %Rc %newoldrc, ptr %stkrc
|
|
458
|
+
|
|
459
|
+
%newhead = call ptr @malloc(i64 112)
|
|
460
|
+
br label %loop
|
|
461
|
+
|
|
462
|
+
loop:
|
|
463
|
+
%old = phi %Stk [%stk, %copy], [%rest, %next]
|
|
464
|
+
%newstk = phi %Stk [%newhead, %copy], [%nextnew, %next]
|
|
465
|
+
|
|
466
|
+
%stkmem = getelementptr %StkVal, %Stk %old, i64 0, i32 1
|
|
467
|
+
%stkregion = getelementptr %StkVal, %Stk %old, i64 0, i32 2
|
|
468
|
+
%stkrest = getelementptr %StkVal, %Stk %old, i64 0, i32 3
|
|
469
|
+
|
|
470
|
+
%mem = load %Mem, ptr %stkmem
|
|
471
|
+
%region = load %Region, ptr %stkregion
|
|
472
|
+
%rest = load %Stk, ptr %stkrest
|
|
473
|
+
|
|
474
|
+
%newstkrc = getelementptr %StkVal, %Stk %newstk, i64 0, i32 0
|
|
475
|
+
%newstkmem = getelementptr %StkVal, %Stk %newstk, i64 0, i32 1
|
|
476
|
+
%newstkregion = getelementptr %StkVal, %Stk %newstk, i64 0, i32 2
|
|
477
|
+
%newstkrest = getelementptr %StkVal, %Stk %newstk, i64 0, i32 3
|
|
478
|
+
|
|
479
|
+
%newmem = call %Mem @copyMem(%Mem %mem)
|
|
480
|
+
|
|
481
|
+
%newsp = extractvalue %Mem %newmem, 0
|
|
482
|
+
call fastcc void @shareFrames(%Sp %newsp)
|
|
483
|
+
|
|
484
|
+
%newregion = call %Region @copyRegion(%Region %region)
|
|
485
|
+
|
|
486
|
+
store %Rc 0, ptr %newstkrc
|
|
487
|
+
store %Mem %newmem, ptr %newstkmem
|
|
488
|
+
store %Region %newregion, ptr %newstkregion
|
|
489
|
+
|
|
490
|
+
%last = icmp eq %Stk %rest, %stk
|
|
491
|
+
br i1 %last, label %closecycle, label %next
|
|
492
|
+
|
|
493
|
+
next:
|
|
494
|
+
%nextnew = call ptr @malloc(i64 112)
|
|
495
|
+
store %Stk %nextnew, ptr %newstkrest
|
|
496
|
+
br label %loop
|
|
497
|
+
|
|
498
|
+
closecycle:
|
|
499
|
+
store %Stk %newhead, ptr %newstkrest
|
|
500
|
+
ret %Stk %newhead
|
|
501
|
+
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
define void @shareStack(%Stk %stk) alwaysinline {
|
|
505
|
+
%stkrc = getelementptr %StkVal, %Stk %stk, i64 0, i32 0
|
|
506
|
+
%rc = load %Rc, ptr %stkrc
|
|
507
|
+
%rc.1 = add %Rc %rc, 1
|
|
508
|
+
store %Rc %rc.1, ptr %stkrc
|
|
509
|
+
ret void
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
define void @eraseStack(%Stk %stk) alwaysinline {
|
|
513
|
+
%stkrc = getelementptr %StkVal, %Stk %stk, i64 0, i32 0
|
|
514
|
+
%rc = load %Rc, ptr %stkrc
|
|
515
|
+
switch %Rc %rc, label %decr [%Rc 0, label %free]
|
|
516
|
+
|
|
517
|
+
decr:
|
|
518
|
+
%rc.1 = sub %Rc %rc, 1
|
|
519
|
+
store %Rc %rc.1, ptr %stkrc
|
|
520
|
+
ret void
|
|
521
|
+
|
|
522
|
+
free:
|
|
523
|
+
%stksp = getelementptr %StkVal, %Stk %stk, i64 0, i32 1, i32 0
|
|
524
|
+
%sp = load %Sp, ptr %stksp
|
|
525
|
+
call fastcc void @eraseFrames(%Sp %sp)
|
|
526
|
+
|
|
527
|
+
%regionp = getelementptr %StkVal, %Stk %stk, i64 0, i32 2
|
|
528
|
+
%region = load %Region, ptr %regionp
|
|
529
|
+
|
|
530
|
+
call void @eraseRegion(%Region %region)
|
|
531
|
+
|
|
532
|
+
call void @free(%Stk %stk)
|
|
533
|
+
ret void
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
define fastcc void @shareFrames(%Sp %sp) alwaysinline {
|
|
537
|
+
%newsp = getelementptr %FrameHeader, %Sp %sp, i64 -1
|
|
538
|
+
%stksharer = getelementptr %FrameHeader, %Sp %newsp, i64 0, i32 1
|
|
539
|
+
%sharer = load %Sharer, ptr %stksharer
|
|
540
|
+
tail call fastcc void %sharer(%Sp %newsp)
|
|
541
|
+
ret void
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
define fastcc void @eraseFrames(%Sp %sp) alwaysinline {
|
|
545
|
+
%newsp = getelementptr %FrameHeader, %Sp %sp, i64 -1
|
|
546
|
+
%stkeraser = getelementptr %FrameHeader, %Sp %newsp, i64 0, i32 2
|
|
547
|
+
%eraser = load %Eraser, ptr %stkeraser
|
|
548
|
+
tail call fastcc void %eraser(%Sp %newsp)
|
|
549
|
+
ret void
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
define void @forEachObject(ptr %elementp, ptr %end, ptr %f) alwaysinline {
|
|
553
|
+
%done = icmp uge ptr %elementp, %end
|
|
554
|
+
br i1 %done, label %return, label %erase
|
|
555
|
+
|
|
556
|
+
erase:
|
|
557
|
+
%element = load %Pos, ptr %elementp
|
|
558
|
+
call void %f(%Pos %element)
|
|
559
|
+
|
|
560
|
+
%nextelementp = getelementptr %Pos, ptr %elementp, i64 1
|
|
561
|
+
tail call void @forEachObject(ptr %nextelementp, ptr %end, ptr %f)
|
|
562
|
+
ret void
|
|
563
|
+
|
|
564
|
+
return:
|
|
565
|
+
ret void
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
define void @eraseRegion(%Region %region) alwaysinline {
|
|
569
|
+
%valuesbase = extractvalue %Region %region, 0, 1
|
|
570
|
+
call void @free(%Base %valuesbase)
|
|
571
|
+
|
|
572
|
+
%objectsbase = extractvalue %Region %region, 1, 1
|
|
573
|
+
%objectssp = extractvalue %Region %region, 1, 0
|
|
574
|
+
call void @forEachObject(%Base %objectsbase, %Sp %objectssp, %Eraser @erasePositive)
|
|
575
|
+
call void @free(%Base %objectsbase)
|
|
576
|
+
|
|
577
|
+
%stringsbase = extractvalue %Region %region, 2, 1
|
|
578
|
+
%stringssp = extractvalue %Region %region, 2, 0
|
|
579
|
+
call void @forEachObject(%Base %stringsbase, %Sp %stringssp, %Eraser @c_buffer_refcount_decrement)
|
|
580
|
+
call void @free(%Base %stringsbase)
|
|
581
|
+
|
|
582
|
+
ret void
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
; RTS initialization
|
|
586
|
+
|
|
587
|
+
define fastcc void @topLevel(%Env %env, %Sp noalias %sp) {
|
|
588
|
+
%base = load %Base, ptr @base
|
|
589
|
+
call void @free(%Base %base)
|
|
590
|
+
|
|
591
|
+
%region = load %Region, ptr @region
|
|
592
|
+
%base.0 = extractvalue %Region %region, 0, 1
|
|
593
|
+
%base.1 = extractvalue %Region %region, 1, 1
|
|
594
|
+
%base.2 = extractvalue %Region %region, 2, 1
|
|
595
|
+
|
|
596
|
+
call void @free(%Base %base.0)
|
|
597
|
+
call void @free(%Base %base.1)
|
|
598
|
+
call void @free(%Base %base.2)
|
|
599
|
+
|
|
600
|
+
call void @free(%Env %env)
|
|
601
|
+
ret void
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
define fastcc void @topLevelSharer(%Env %env) {
|
|
605
|
+
; TODO this should never be called
|
|
606
|
+
ret void
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
define fastcc void @topLevelEraser(%Env %env) {
|
|
610
|
+
; TODO this should never be called
|
|
611
|
+
ret void
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
; Primitive Types
|
|
615
|
+
|
|
616
|
+
%Int = type i64
|
|
617
|
+
%Double = type double
|
|
618
|
+
|
|
619
|
+
%Evi = type i64
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#ifndef EFFEKT_SANITY_C
|
|
2
|
+
#define EFFEKT_SANITY_C
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
#if CHAR_BIT != 8
|
|
6
|
+
#error Machine ought to have eight bits in a byte.
|
|
7
|
+
#endif
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
#define ASSERT_NON_NULL(PTR) if ((PTR) == NULL) { \
|
|
11
|
+
fprintf(stderr, "*** MALLOC PANIC\n"); \
|
|
12
|
+
fflush(stderr); \
|
|
13
|
+
exit(1); }
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
#endif
|