@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.
Files changed (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +36 -0
  3. package/bin/effekt +0 -0
  4. package/bin/effekt.sh +2 -0
  5. package/libraries/chez/THIRD-PARTY.txt +11 -0
  6. package/libraries/chez/callcc/datatype.ss +188 -0
  7. package/libraries/chez/callcc/effekt.effekt +221 -0
  8. package/libraries/chez/callcc/effekt.ss +31 -0
  9. package/libraries/chez/callcc/seq.ss +44 -0
  10. package/libraries/chez/callcc/seq0.ss +69 -0
  11. package/libraries/chez/callcc/tail.ss +76 -0
  12. package/libraries/chez/callcc/tail0.ss +89 -0
  13. package/libraries/chez/common/effekt_matching.ss +100 -0
  14. package/libraries/chez/common/effekt_primitives.ss +97 -0
  15. package/libraries/chez/common/immutable/cslist.effekt +31 -0
  16. package/libraries/chez/common/immutable/dequeue.effekt +78 -0
  17. package/libraries/chez/common/immutable/list.effekt +643 -0
  18. package/libraries/chez/common/immutable/option.effekt +39 -0
  19. package/libraries/chez/common/immutable/result.effekt +29 -0
  20. package/libraries/chez/common/io/args.effekt +20 -0
  21. package/libraries/chez/common/mutable/array.effekt +27 -0
  22. package/libraries/chez/common/mutable/dict.effekt +30 -0
  23. package/libraries/chez/common/mutable/heap.effekt +12 -0
  24. package/libraries/chez/common/test.effekt +59 -0
  25. package/libraries/chez/common/text/pregexp.scm +772 -0
  26. package/libraries/chez/common/text/regex.effekt +33 -0
  27. package/libraries/chez/common/text/string.effekt +46 -0
  28. package/libraries/chez/lift/effekt.effekt +217 -0
  29. package/libraries/chez/lift/effekt.ss +118 -0
  30. package/libraries/chez/monadic/effekt.effekt +218 -0
  31. package/libraries/chez/monadic/effekt.ss +84 -0
  32. package/libraries/chez/monadic/seq0.ss +76 -0
  33. package/libraries/js/effekt.effekt +284 -0
  34. package/libraries/js/effekt_builtins.js +26 -0
  35. package/libraries/js/effekt_matching.js +79 -0
  36. package/libraries/js/effekt_runtime.js +385 -0
  37. package/libraries/js/immutable/dequeue.effekt +78 -0
  38. package/libraries/js/immutable/list.effekt +643 -0
  39. package/libraries/js/immutable/option.effekt +49 -0
  40. package/libraries/js/immutable/result.effekt +29 -0
  41. package/libraries/js/io/args.effekt +9 -0
  42. package/libraries/js/io/async.effekt +28 -0
  43. package/libraries/js/io/async.js +2 -0
  44. package/libraries/js/io/file.effekt +50 -0
  45. package/libraries/js/io/file_include.js +13 -0
  46. package/libraries/js/mutable/array.effekt +98 -0
  47. package/libraries/js/mutable/heap.effekt +32 -0
  48. package/libraries/js/mutable/map.effekt +32 -0
  49. package/libraries/js/test.effekt +59 -0
  50. package/libraries/js/text/regex.effekt +34 -0
  51. package/libraries/js/text/string.effekt +64 -0
  52. package/libraries/js/unsafe/cont.effekt +11 -0
  53. package/libraries/js/web/dom.effekt +45 -0
  54. package/libraries/llvm/buffer.c +181 -0
  55. package/libraries/llvm/effekt.effekt +243 -0
  56. package/libraries/llvm/forward-declare-c.ll +24 -0
  57. package/libraries/llvm/hole.c +11 -0
  58. package/libraries/llvm/immutable/list.effekt +678 -0
  59. package/libraries/llvm/immutable/option.effekt +53 -0
  60. package/libraries/llvm/immutable/result.effekt +29 -0
  61. package/libraries/llvm/io/args.effekt +24 -0
  62. package/libraries/llvm/io.c +24 -0
  63. package/libraries/llvm/main.c +39 -0
  64. package/libraries/llvm/rts.ll +619 -0
  65. package/libraries/llvm/sanity.c +16 -0
  66. package/libraries/llvm/text/string.effekt +179 -0
  67. package/libraries/llvm/types.c +20 -0
  68. package/libraries/ml/effekt.effekt +267 -0
  69. package/libraries/ml/effekt.sml +63 -0
  70. package/libraries/ml/immutable/dequeue.effekt +81 -0
  71. package/libraries/ml/immutable/list.effekt +674 -0
  72. package/libraries/ml/immutable/option.effekt +53 -0
  73. package/libraries/ml/immutable/result.effekt +29 -0
  74. package/libraries/ml/immutable/seq.effekt +903 -0
  75. package/libraries/ml/internal/option.effekt +18 -0
  76. package/libraries/ml/io/args.effekt +41 -0
  77. package/libraries/ml/mutable/array.effekt +43 -0
  78. package/libraries/ml/random.effekt +85 -0
  79. package/libraries/ml/test.effekt +60 -0
  80. package/libraries/ml/text/regex.effekt +107 -0
  81. package/libraries/ml/text/string.effekt +81 -0
  82. package/licenses/THIRD-PARTY.txt +21 -0
  83. package/licenses/apache-2.0 - license-2.0.txt +202 -0
  84. package/licenses/eclipse public license, version 2.0 - epl-2.0.html +61 -0
  85. package/licenses/kiama-license.txt +373 -0
  86. package/licenses/kiama-readme.txt +186 -0
  87. package/licenses/mit license - mit-license.html +769 -0
  88. package/licenses/the apache software license, version 2.0 - license-2.0.txt +202 -0
  89. package/licenses/the bsd license - bsd-license.html +762 -0
  90. package/licenses/the mit license - mit.html +769 -0
  91. 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