@effekt-lang/effekt 0.2.1 → 0.3.0

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 (75) 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.ss +31 -0
  8. package/libraries/chez/callcc/seq.ss +44 -0
  9. package/libraries/chez/callcc/seq0.ss +69 -0
  10. package/libraries/chez/callcc/tail.ss +76 -0
  11. package/libraries/chez/callcc/tail0.ss +89 -0
  12. package/libraries/chez/common/effekt_primitives.ss +105 -0
  13. package/libraries/chez/common/immutable/cslist.effekt +37 -0
  14. package/libraries/chez/common/mutable/dict.effekt +28 -0
  15. package/libraries/chez/common/text/pregexp.scm +772 -0
  16. package/libraries/chez/common/text/regex.effekt +31 -0
  17. package/libraries/chez/lift/effekt.ss +118 -0
  18. package/libraries/chez/monadic/effekt.ss +84 -0
  19. package/libraries/chez/monadic/seq0.ss +76 -0
  20. package/libraries/common/args.effekt +95 -0
  21. package/libraries/common/array.effekt +225 -0
  22. package/libraries/common/bench.effekt +60 -0
  23. package/libraries/common/buffer.effekt +123 -0
  24. package/libraries/common/bytes.effekt +125 -0
  25. package/libraries/common/dequeue.effekt +92 -0
  26. package/libraries/common/effekt.effekt +764 -0
  27. package/libraries/common/exception.effekt +122 -0
  28. package/libraries/common/io/console.effekt +66 -0
  29. package/libraries/common/io/error.effekt +365 -0
  30. package/libraries/common/io/files.effekt +282 -0
  31. package/libraries/common/io/network.effekt +105 -0
  32. package/libraries/common/io/time.effekt +15 -0
  33. package/libraries/common/io.effekt +158 -0
  34. package/libraries/common/list.effekt +687 -0
  35. package/libraries/common/option.effekt +72 -0
  36. package/libraries/common/process.effekt +10 -0
  37. package/libraries/common/queue.effekt +140 -0
  38. package/libraries/common/ref.effekt +63 -0
  39. package/libraries/common/result.effekt +45 -0
  40. package/libraries/common/seq.effekt +914 -0
  41. package/libraries/common/string.effekt +395 -0
  42. package/libraries/common/test.effekt +98 -0
  43. package/libraries/js/effekt_builtins.js +57 -0
  44. package/libraries/js/effekt_runtime.js +385 -0
  45. package/libraries/js/io.js +143 -0
  46. package/libraries/js/mutable/map.effekt +31 -0
  47. package/libraries/js/text/regex.effekt +33 -0
  48. package/libraries/js/unsafe/cont.effekt +11 -0
  49. package/libraries/js/web/dom.effekt +45 -0
  50. package/libraries/llvm/array.c +53 -0
  51. package/libraries/llvm/buffer.c +286 -0
  52. package/libraries/llvm/forward-declare-c.ll +43 -0
  53. package/libraries/llvm/hole.c +11 -0
  54. package/libraries/llvm/io.c +566 -0
  55. package/libraries/llvm/io.ll +19 -0
  56. package/libraries/llvm/main.c +41 -0
  57. package/libraries/llvm/ref.c +45 -0
  58. package/libraries/llvm/rts.ll +761 -0
  59. package/libraries/llvm/sanity.c +16 -0
  60. package/libraries/llvm/types.c +43 -0
  61. package/libraries/ml/effekt.sml +65 -0
  62. package/libraries/ml/internal/mllist.effekt +9 -0
  63. package/libraries/ml/internal/mloption.effekt +18 -0
  64. package/libraries/ml/random.effekt +85 -0
  65. package/libraries/ml/text/regex.effekt +102 -0
  66. package/licenses/THIRD-PARTY.txt +21 -0
  67. package/licenses/apache-2.0 - license-2.0.txt +202 -0
  68. package/licenses/eclipse public license, version 2.0 - epl-2.0.html +61 -0
  69. package/licenses/kiama-license.txt +373 -0
  70. package/licenses/kiama-readme.txt +186 -0
  71. package/licenses/mit license - mit-license.html +1239 -0
  72. package/licenses/the apache software license, version 2.0 - license-2.0.txt +202 -0
  73. package/licenses/the bsd license - bsd-license.html +1237 -0
  74. package/licenses/the mit license - mit.html +1239 -0
  75. package/package.json +26 -18
@@ -0,0 +1,761 @@
1
+ ; Run-Time System
2
+
3
+ %Evidence = type i64
4
+
5
+ ; Basic types
6
+
7
+ %Environment = type ptr
8
+
9
+ ; Reference counts
10
+ %ReferenceCount = type i64
11
+
12
+ ; Code to share (bump rc) an environment
13
+ %Sharer = type ptr
14
+
15
+ ; Code to drop an environment
16
+ %Eraser = type ptr
17
+
18
+ ; Every heap object starts with a header
19
+ %Header = type {%ReferenceCount, %Eraser}
20
+
21
+ ; A heap object is a pointer to a header followed by payload.
22
+ ;
23
+ ; +--[ Header ]--------------+-------------+
24
+ ; | ReferenceCount | Eraser | Payload ... |
25
+ ; +-----------------+--------+-------------+
26
+ %Object = type ptr
27
+
28
+
29
+ ; A Frame has the following layout
30
+ ;
31
+ ; +-------[ FrameHeader ]------------+--------------+
32
+ ; | ReturnAddress | Sharer | Eraser | Payload ... |
33
+ ; +----------------------------------+--------------+
34
+
35
+ ; A stack pointer points to the top-most frame followed by all other frames.
36
+ ;
37
+ ; For example
38
+ ;
39
+ ; +--------------------+ <- Limit
40
+ ; : :
41
+ ; : : <- StackPointer
42
+ ; +--------------------+
43
+ ; | FrameHeader |
44
+ ; | z |
45
+ ; | y |
46
+ ; | x |
47
+ ; +--------------------+
48
+ ; | ... next frame ... |
49
+ ; +--------------------+
50
+ ; : ... :
51
+ ; +--------------------+ <- Base
52
+ %StackPointer = type ptr
53
+ %Base = type %StackPointer
54
+ %Limit = type %StackPointer
55
+ %ReturnAddress = type ptr
56
+ %FrameHeader = type { %ReturnAddress, %Sharer, %Eraser }
57
+
58
+ ; Pointers for a heap allocated stack
59
+ %Memory = type { %StackPointer, %Base, %Limit }
60
+
61
+ ; The garbage collector differentiates three groups of types:
62
+ ; - Values (Integer, Double)
63
+ ; - Objects (Positive, Negative)
64
+ ; - Strings
65
+ ; For each group we have an arena where mutable state is allocated.
66
+ ;
67
+ %Region = type [ 3 x %Memory ]
68
+
69
+ ; The "meta" stack (a stack of stacks) -- a pointer to a %StackValue
70
+ %Stack = type ptr
71
+
72
+ ; Unique tags to index into the stack.
73
+ %Prompt = type i64
74
+
75
+ ; fresh prompt generation
76
+ @lastPrompt = private global %Prompt 0
77
+
78
+ ; This is used for two purposes:
79
+ ; - a refied first-class list of stacks (cyclic linked-list)
80
+ ; - as part of an intrusive linked-list of stacks (meta stack)
81
+ %StackValue = type { %ReferenceCount, %Memory, %Region, %Prompt, %Stack }
82
+
83
+
84
+
85
+
86
+ ; Positive data types consist of a (type-local) tag and a heap object
87
+ %Pos = type {i64, %Object}
88
+
89
+ ; Negative types (codata) consist of a vtable and a heap object
90
+ %Neg = type {ptr, %Object}
91
+
92
+ ; Reference into an arena (prompt -- cast to 32bit, offset 32bit)
93
+ %Reference = type {i32, i32}
94
+
95
+ ; Builtin Types
96
+
97
+ %Int = type i64
98
+ %Double = type double
99
+ %Byte = type i8
100
+ %Char = type i64
101
+ %Bool = type %Pos
102
+ %Unit = type %Pos
103
+ %String = type %Pos
104
+
105
+ ; Foreign imports
106
+
107
+ declare ptr @malloc(i64)
108
+ declare void @free(ptr)
109
+ declare ptr @realloc(ptr, i64)
110
+ declare void @memcpy(ptr, ptr, i64)
111
+ declare i64 @llvm.ctlz.i64 (i64 , i1)
112
+ declare i64 @llvm.fshr.i64(i64, i64, i64)
113
+ declare void @print(i64)
114
+ declare void @exit(i64)
115
+
116
+
117
+ ; Prompts
118
+
119
+ define %Prompt @currentPrompt(%Stack %stack) {
120
+ %prompt_pointer = getelementptr %StackValue, ptr %stack, i64 0, i32 3
121
+ %prompt = load %Prompt, ptr %prompt_pointer
122
+ ret %Prompt %prompt
123
+ }
124
+
125
+ define %Prompt @freshPrompt() {
126
+ %currentPrompt = load %Prompt, ptr @lastPrompt
127
+ %newPrompt = add %Prompt %currentPrompt, 1
128
+ store %Prompt %newPrompt, ptr @lastPrompt
129
+ ret %Prompt %newPrompt
130
+ }
131
+
132
+ ; Garbage collection
133
+
134
+ define %Object @newObject(%Eraser %eraser, i64 %environmentSize) alwaysinline {
135
+ ; This magical 16 is the size of the object header
136
+ %size = add i64 %environmentSize, 16
137
+ %object = call ptr @malloc(i64 %size)
138
+ %objectReferenceCount = getelementptr %Header, ptr %object, i64 0, i32 0
139
+ %objectEraser = getelementptr %Header, ptr %object, i64 0, i32 1
140
+ store %ReferenceCount 0, ptr %objectReferenceCount
141
+ store %Eraser %eraser, ptr %objectEraser
142
+ ret %Object %object
143
+ }
144
+
145
+ define %Environment @objectEnvironment(%Object %object) alwaysinline {
146
+ ; Environment is stored right after header
147
+ %environment = getelementptr %Header, ptr %object, i64 1
148
+ ret %Environment %environment
149
+ }
150
+
151
+ define void @shareObject(%Object %object) alwaysinline {
152
+ %isNull = icmp eq %Object %object, null
153
+ br i1 %isNull, label %done, label %next
154
+
155
+ next:
156
+ %objectReferenceCount = getelementptr %Header, ptr %object, i64 0, i32 0
157
+ %referenceCount = load %ReferenceCount, ptr %objectReferenceCount
158
+ %referenceCount.1 = add %ReferenceCount %referenceCount, 1
159
+ store %ReferenceCount %referenceCount.1, ptr %objectReferenceCount
160
+ br label %done
161
+
162
+ done:
163
+ ret void
164
+ }
165
+
166
+ define void @sharePositive(%Pos %val) alwaysinline {
167
+ %object = extractvalue %Pos %val, 1
168
+ tail call void @shareObject(%Object %object)
169
+ ret void
170
+ }
171
+
172
+ define void @shareNegative(%Neg %val) alwaysinline {
173
+ %object = extractvalue %Neg %val, 1
174
+ tail call void @shareObject(%Object %object)
175
+ ret void
176
+ }
177
+
178
+ define void @eraseObject(%Object %object) alwaysinline {
179
+ %isNull = icmp eq %Object %object, null
180
+ br i1 %isNull, label %done, label %next
181
+
182
+ next:
183
+ %objectReferenceCount = getelementptr %Header, ptr %object, i64 0, i32 0
184
+ %referenceCount = load %ReferenceCount, ptr %objectReferenceCount
185
+ switch %ReferenceCount %referenceCount, label %decr [%ReferenceCount 0, label %free]
186
+
187
+ decr:
188
+ %referenceCount.1 = sub %ReferenceCount %referenceCount, 1
189
+ store %ReferenceCount %referenceCount.1, ptr %objectReferenceCount
190
+ ret void
191
+
192
+ free:
193
+ %objectEraser = getelementptr %Header, ptr %object, i64 0, i32 1
194
+ %eraser = load %Eraser, ptr %objectEraser
195
+ %environment = call %Environment @objectEnvironment(%Object %object)
196
+ call void %eraser(%Environment %environment)
197
+ call void @free(%Object %object)
198
+ br label %done
199
+
200
+ done:
201
+ ret void
202
+ }
203
+
204
+ define void @erasePositive(%Pos %val) alwaysinline {
205
+ %object = extractvalue %Pos %val, 1
206
+ tail call void @eraseObject(%Object %object)
207
+ ret void
208
+ }
209
+
210
+ define void @eraseNegative(%Neg %val) alwaysinline {
211
+ %object = extractvalue %Neg %val, 1
212
+ tail call void @eraseObject(%Object %object)
213
+ ret void
214
+ }
215
+
216
+
217
+ ; Arena management
218
+ define ptr @getRegionPointer(%Prompt %prompt, %Stack %stack) {
219
+ entry:
220
+ %prompt_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 3
221
+ %currentPrompt = load %Prompt, ptr %prompt_pointer
222
+ %promptMatch = icmp eq %Prompt %currentPrompt, %prompt
223
+ br i1 %promptMatch, label %found, label %continue
224
+
225
+ continue:
226
+ %nextStack_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
227
+ %nextStack = load %Stack, ptr %nextStack_pointer
228
+ %region = tail call ptr @getRegionPointer(%Prompt %prompt, %Stack %nextStack)
229
+ ret ptr %region
230
+
231
+ found:
232
+ %stackRegion = getelementptr %StackValue, %Stack %stack, i64 0, i32 2
233
+ ret ptr %stackRegion
234
+ }
235
+
236
+ define { ptr, %Reference } @alloc(i64 %index, %Prompt %prompt, %Stack %stack) alwaysinline {
237
+ %region_pointer = call ptr @getRegionPointer(%Prompt %prompt, %Stack %stack)
238
+
239
+ %stackPointer_pointer = getelementptr %Region, ptr %region_pointer, i64 0, i64 %index, i32 0
240
+ %base_pointer = getelementptr %Region, ptr %region_pointer, i64 0, i64 %index, i32 1
241
+ %limit_pointer = getelementptr %Region, ptr %region_pointer, i64 0, i64 %index, i32 2
242
+
243
+ %stackPointer = load %StackPointer, ptr %stackPointer_pointer
244
+ %base = load %Base, ptr %base_pointer
245
+ %limit = load %Limit, ptr %limit_pointer
246
+
247
+ %object = icmp ne i64 %index, 0
248
+ %size = select i1 %object, i64 16, i64 8
249
+
250
+ %nextStackPointer = getelementptr i8, %StackPointer %stackPointer, i64 %size
251
+
252
+ %cmp = icmp ule %StackPointer %nextStackPointer, %limit
253
+ br i1 %cmp, label %continue, label %realloc
254
+
255
+ continue:
256
+ store %StackPointer %nextStackPointer, ptr %stackPointer_pointer
257
+ %intBase = ptrtoint %Base %base to i64
258
+ %intStackPointer = ptrtoint %StackPointer %stackPointer to i64
259
+ %offset64 = sub i64 %intStackPointer, %intBase
260
+
261
+ %prompt32 = trunc i64 %prompt to i32
262
+ %offset32 = trunc i64 %offset64 to i32
263
+
264
+ %ret.0 = insertvalue { ptr, %Reference } undef, %StackPointer %stackPointer, 0
265
+ %ref.1 = insertvalue %Reference undef, i32 %prompt32, 0
266
+ %ref.2 = insertvalue %Reference %ref.1, i32 %offset32, 1
267
+ %ret.1 = insertvalue { ptr, %Reference } %ret.0, %Reference %ref.2, 1
268
+ ret { ptr, %Reference } %ret.1
269
+
270
+ realloc:
271
+ %intBase_2 = ptrtoint %Base %base to i64
272
+ %intLimit = ptrtoint %Limit %limit to i64
273
+ %arenaSize = sub i64 %intLimit, %intBase_2
274
+ %empty = icmp eq i64 %arenaSize, 0
275
+ %double = mul i64 %arenaSize, 2
276
+ %newArenaSize = select i1 %empty, i64 1024, i64 %double
277
+
278
+ %newBase = call ptr @realloc(ptr %base, i64 %newArenaSize)
279
+ %newlimit = getelementptr i8, %Base %newBase, i64 %newArenaSize
280
+ %newStackPointer = getelementptr i8, %Base %newBase, i64 %arenaSize
281
+ %newNextStackPointer = getelementptr i8, %StackPointer %newStackPointer, i64 %size
282
+
283
+ store %Base %newBase, ptr %base_pointer
284
+ store %Limit %newlimit, ptr %limit_pointer
285
+ store %StackPointer %newNextStackPointer, ptr %stackPointer_pointer
286
+
287
+ %prompt32_2 = trunc i64 %prompt to i32
288
+ %arenaSize32 = trunc i64 %arenaSize to i32
289
+
290
+ %ret..0 = insertvalue { ptr, %Reference } undef, %StackPointer %newStackPointer, 0
291
+ %ref..1 = insertvalue %Reference undef, i32 %prompt32_2, 0
292
+ %ref..2 = insertvalue %Reference %ref..1, i32 %arenaSize32, 1
293
+ %ret..1 = insertvalue { ptr, %Reference } %ret..0, %Reference %ref..2, 1
294
+ ret { ptr, %Reference } %ret..1
295
+ }
296
+
297
+
298
+ define ptr @getPointer(%Reference %reference, i64 %index, %Stack %stack) {
299
+ %prompt32 = extractvalue %Reference %reference, 0
300
+ %offset32 = extractvalue %Reference %reference, 1
301
+ %prompt = zext i32 %prompt32 to i64
302
+ %offset = zext i32 %offset32 to i64
303
+
304
+ %region_pointer = call ptr @getRegionPointer(%Prompt %prompt, %Stack %stack)
305
+ %base_pointer = getelementptr %Region, ptr %region_pointer, i64 0, i64 %index, i32 1
306
+ %base = load %Base, ptr %base_pointer
307
+ %pointer = getelementptr i8, ptr %base, i64 %offset
308
+ ret ptr %pointer
309
+ }
310
+
311
+ define %Stack @getStack(%Stack %stack, %Prompt %prompt) {
312
+ %promptPointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 3
313
+ %thisPrompt = load %Prompt, ptr %promptPointer
314
+ %found = icmp eq %Prompt %prompt, %thisPrompt
315
+ br i1 %found, label %done, label %recurse
316
+
317
+ done:
318
+ ret %Stack %stack
319
+
320
+ recurse:
321
+ %nextStackPointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
322
+ %nextStack = load %Stack, ptr %nextStackPointer
323
+ %result = call %Stack @getStack(%Stack %nextStack, %Prompt %prompt)
324
+ ret %Stack %result
325
+ }
326
+
327
+ define ptr @getVarPointer(%Reference %reference, %Stack %stack) {
328
+ %prompt32 = extractvalue %Reference %reference, 0
329
+ %offset32 = extractvalue %Reference %reference, 1
330
+ %prompt = zext i32 %prompt32 to i64
331
+ %offset = zext i32 %offset32 to i64
332
+
333
+ %targetStack = call %Stack @getStack(%Stack %stack, %Prompt %prompt)
334
+ %basePointer = getelementptr %StackValue, %Stack %targetStack, i64 0, i32 1, i32 1
335
+ %base = load %Base, ptr %basePointer
336
+ %varPointer = getelementptr i8, %Base %base, i64 %offset
337
+ ret ptr %varPointer
338
+ }
339
+
340
+ define %Reference @newReference(%Stack %stack) alwaysinline {
341
+ %stackPointerPointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 0
342
+ %basePointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 1
343
+
344
+ %stackPointer = load %StackPointer, ptr %stackPointerPointer
345
+ %base = load %StackPointer, ptr %basePointer
346
+
347
+ %intStack = ptrtoint %StackPointer %stackPointer to i64
348
+ %intBase = ptrtoint %StackPointer %base to i64
349
+
350
+ %offset = sub i64 %intStack, %intBase
351
+ %offset32 = trunc i64 %offset to i32
352
+
353
+ %prompt = call %Prompt @currentPrompt(%Stack %stack)
354
+ %prompt32 = trunc %Prompt %prompt to i32
355
+
356
+ %reference..1 = insertvalue %Reference undef, i32 %prompt32, 0
357
+ %reference = insertvalue %Reference %reference..1, i32 %offset32, 1
358
+
359
+ ret %Reference %reference
360
+ }
361
+
362
+ ; Stack management
363
+
364
+ define %StackPointer @stackAllocate(%Stack %stack, i64 %n) {
365
+ %stackStackPointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 0
366
+ %stackPointer = load %StackPointer, ptr %stackStackPointer
367
+
368
+ %stackPointer_2 = getelementptr i8, %StackPointer %stackPointer, i64 %n
369
+ store %StackPointer %stackPointer_2, ptr %stackStackPointer
370
+ ret %StackPointer %stackPointer
371
+ }
372
+
373
+ define %StackPointer @stackDeallocate(%Stack %stack, i64 %n) {
374
+ %stackStackPointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 0
375
+ %stackPointer = load %StackPointer, ptr %stackStackPointer
376
+
377
+ %o = sub i64 0, %n
378
+ %stackPointer_2 = getelementptr i8, %StackPointer %stackPointer, i64 %o
379
+ store %StackPointer %stackPointer_2, ptr %stackStackPointer
380
+
381
+ ret %StackPointer %stackPointer_2
382
+ }
383
+
384
+ ; Meta-stack management
385
+
386
+ define %Memory @newMemory() {
387
+ %stackPointer = call %StackPointer @malloc(i64 268435456)
388
+ %limit = getelementptr i8, ptr %stackPointer, i64 268435456
389
+
390
+ %memory.0 = insertvalue %Memory undef, %StackPointer %stackPointer, 0
391
+ %memory.1 = insertvalue %Memory %memory.0, %Base %stackPointer, 1
392
+ %memory.2 = insertvalue %Memory %memory.1, %Limit %limit, 2
393
+
394
+ ret %Memory %memory.2
395
+ }
396
+
397
+ define %Stack @newStack(%Prompt %prompt) {
398
+
399
+ ; TODO find actual size of stack
400
+ %stack = call ptr @malloc(i64 120)
401
+
402
+ ; TODO initialize to zero and grow later
403
+ %stackMemory = call %Memory @newMemory()
404
+
405
+ %stack.0 = insertvalue %StackValue undef, %ReferenceCount 0, 0
406
+ %stack.1 = insertvalue %StackValue %stack.0, %Memory %stackMemory, 1
407
+ %stack.2 = insertvalue %StackValue %stack.1, %Region zeroinitializer, 2
408
+ %stack.3 = insertvalue %StackValue %stack.2, %Prompt %prompt, 3
409
+ %stack.4 = insertvalue %StackValue %stack.3, %Stack zeroinitializer, 4
410
+
411
+ store %StackValue %stack.4, %Stack %stack
412
+
413
+ ret %Stack %stack
414
+ }
415
+
416
+ define void @pushStack(%Stack %stack, %Stack %oldStack) {
417
+ %stackRest = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
418
+ %rest = load %Stack, ptr %stackRest
419
+ %isNull = icmp eq %Stack %rest, null
420
+ br i1 %isNull, label %done, label %next
421
+
422
+ done:
423
+ store %Stack %oldStack, ptr %stackRest
424
+ ret void
425
+
426
+ next:
427
+ tail call void @pushStack(%Stack %rest, %Stack %oldStack)
428
+ ret void
429
+ }
430
+
431
+ define %Stack @popStacks(%Stack %stack, %Prompt %prompt) {
432
+ entry:
433
+ %prompt_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 3
434
+ %currentPrompt = load %Prompt, ptr %prompt_pointer
435
+ %promptMatch = icmp eq %Prompt %currentPrompt, %prompt
436
+ br i1 %promptMatch, label %found, label %continue
437
+
438
+ continue:
439
+ %nextStack_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
440
+ %nextStack = load %Stack, ptr %nextStack_pointer
441
+ %result = tail call %Stack @popStacks(%Stack %nextStack, %Prompt %prompt)
442
+ ret %Stack %result
443
+
444
+ found:
445
+ %nextStack2_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
446
+ %nextStack2 = load %Stack, ptr %nextStack2_pointer
447
+ store %Stack null, ptr %nextStack2_pointer
448
+ ret %Stack %nextStack2
449
+ }
450
+
451
+ define void @eraseMemory(%Memory %memory) {
452
+ %stackPointer = extractvalue %Memory %memory, 0
453
+ call void @free(%StackPointer %stackPointer)
454
+ ret void
455
+ }
456
+
457
+ define void @forEachObject(ptr %elementPointer, ptr %end, ptr %f) alwaysinline {
458
+ %done = icmp uge ptr %elementPointer, %end
459
+ br i1 %done, label %return, label %erase
460
+
461
+ erase:
462
+ %element = load %Pos, ptr %elementPointer
463
+ call void %f(%Pos %element)
464
+
465
+ %nextElementPointer = getelementptr %Pos, ptr %elementPointer, i64 1
466
+ tail call void @forEachObject(ptr %nextElementPointer, ptr %end, ptr %f)
467
+ ret void
468
+
469
+ return:
470
+ ret void
471
+ }
472
+
473
+ define void @eraseRegion(%Region %region) alwaysinline {
474
+ %valuesBase = extractvalue %Region %region, 0, 1
475
+ call void @free(%Base %valuesBase)
476
+
477
+ %objectsBase = extractvalue %Region %region, 1, 1
478
+ %objectsStackPointer = extractvalue %Region %region, 1, 0
479
+ call void @forEachObject(%Base %objectsBase, %StackPointer %objectsStackPointer, %Eraser @erasePositive)
480
+ call void @free(%Base %objectsBase)
481
+
482
+ %stringsBase = extractvalue %Region %region, 2, 1
483
+ %stringsStackPointer = extractvalue %Region %region, 2, 0
484
+ call void @forEachObject(%Base %stringsBase, %StackPointer %stringsStackPointer, %Eraser @erasePositive)
485
+ call void @free(%Base %stringsBase)
486
+
487
+ ret void
488
+ }
489
+
490
+ define %Stack @underflowStack(%Stack %stack) {
491
+ %stackMemory = getelementptr %StackValue, %Stack %stack, i64 0, i32 1
492
+ %stackRegion = getelementptr %StackValue, %Stack %stack, i64 0, i32 2
493
+ %stackRest = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
494
+
495
+ %memory = load %Memory, ptr %stackMemory
496
+ %region = load %Region, ptr %stackRegion
497
+ %rest = load %Stack, ptr %stackRest
498
+
499
+ call void @eraseMemory(%Memory %memory)
500
+ call void @eraseRegion(%Region %region)
501
+ call void @free(%Stack %stack)
502
+
503
+ ret %Stack %rest
504
+ }
505
+
506
+ define %Memory @copyMemory(%Memory %memory) alwaysinline {
507
+ %stackPointer = extractvalue %Memory %memory, 0
508
+ %base = extractvalue %Memory %memory, 1
509
+ %limit = extractvalue %Memory %memory, 2
510
+
511
+ %intStackPointer = ptrtoint %StackPointer %stackPointer to i64
512
+ %intBase = ptrtoint %Base %base to i64
513
+ %intLimit = ptrtoint %Limit %limit to i64
514
+ %used = sub i64 %intStackPointer, %intBase
515
+ %size = sub i64 %intLimit, %intBase
516
+
517
+ %newBase = call ptr @malloc(i64 %size)
518
+ %intNewBase = ptrtoint %Base %newBase to i64
519
+ %intNewStackPointer = add i64 %intNewBase, %used
520
+ %intNewLimit = add i64 %intNewBase, %size
521
+ %newStackPointer = inttoptr i64 %intNewStackPointer to %StackPointer
522
+ %newLimit = inttoptr i64 %intNewLimit to %Limit
523
+
524
+ call void @memcpy(ptr %newBase, ptr %base, i64 %used)
525
+
526
+ %memory.0 = insertvalue %Memory undef, %StackPointer %newStackPointer, 0
527
+ %memory.1 = insertvalue %Memory %memory.0, %Base %newBase, 1
528
+ %memory.2 = insertvalue %Memory %memory.1, %Limit %newLimit, 2
529
+
530
+ ret %Memory %memory.2
531
+ }
532
+
533
+ define %Region @copyRegion(%Region %region) alwaysinline {
534
+ %memory.0 = extractvalue %Region %region, 0
535
+ %memory.1 = extractvalue %Region %region, 1
536
+ %memory.2 = extractvalue %Region %region, 2
537
+
538
+ %objectsBase = extractvalue %Region %region, 1, 1
539
+ %objectsStackPointer = extractvalue %Region %region, 1, 0
540
+ call void @forEachObject(%Base %objectsBase, %StackPointer %objectsStackPointer, %Sharer @sharePositive)
541
+
542
+ %stringsBase = extractvalue %Region %region, 2, 1
543
+ %stringsStackPointer = extractvalue %Region %region, 2, 0
544
+ call void @forEachObject(%Base %stringsBase, %StackPointer %stringsStackPointer, %Sharer @sharePositive)
545
+
546
+ %newMemory.0 = call %Memory @copyMemory(%Memory %memory.0)
547
+ %newMemory.1 = call %Memory @copyMemory(%Memory %memory.1)
548
+ %newMemory.2 = call %Memory @copyMemory(%Memory %memory.2)
549
+
550
+ %region.0 = insertvalue %Region undef, %Memory %newMemory.0, 0
551
+ %region.1 = insertvalue %Region %region.0, %Memory %newMemory.1, 1
552
+ %region.2 = insertvalue %Region %region.1, %Memory %newMemory.2, 2
553
+
554
+ ret %Region %region.2
555
+ }
556
+
557
+ define %Stack @uniqueStack(%Stack %stack) alwaysinline {
558
+
559
+ entry:
560
+ %stackReferenceCount = getelementptr %StackValue, %Stack %stack, i64 0, i32 0
561
+ %referenceCount = load %ReferenceCount, ptr %stackReferenceCount
562
+ switch %ReferenceCount %referenceCount, label %copy [%ReferenceCount 0, label %done]
563
+
564
+ done:
565
+ ret %Stack %stack
566
+
567
+ copy:
568
+ %newOldReferenceCount = sub %ReferenceCount %referenceCount, 1
569
+ store %ReferenceCount %newOldReferenceCount, ptr %stackReferenceCount
570
+
571
+ %newHead = call ptr @malloc(i64 120)
572
+ br label %loop
573
+
574
+ loop:
575
+ %old = phi %Stack [%stack, %copy], [%rest, %next]
576
+ %newStack = phi %Stack [%newHead, %copy], [%nextNew, %next]
577
+
578
+ %stackMemory = getelementptr %StackValue, %Stack %old, i64 0, i32 1
579
+ %stackRegion = getelementptr %StackValue, %Stack %old, i64 0, i32 2
580
+ %stackPrompt = getelementptr %StackValue, %Stack %old, i64 0, i32 3
581
+ %stackRest = getelementptr %StackValue, %Stack %old, i64 0, i32 4
582
+
583
+ %memory = load %Memory, ptr %stackMemory
584
+ %region = load %Region, ptr %stackRegion
585
+ %prompt = load %Prompt, ptr %stackPrompt
586
+ %rest = load %Stack, ptr %stackRest
587
+
588
+ %newStackReferenceCount = getelementptr %StackValue, %Stack %newStack, i64 0, i32 0
589
+ %newStackMemory = getelementptr %StackValue, %Stack %newStack, i64 0, i32 1
590
+ %newStackRegion = getelementptr %StackValue, %Stack %newStack, i64 0, i32 2
591
+ %newStackPrompt = getelementptr %StackValue, %Stack %newStack, i64 0, i32 3
592
+ %newStackRest = getelementptr %StackValue, %Stack %newStack, i64 0, i32 4
593
+
594
+ %newMemory = call %Memory @copyMemory(%Memory %memory)
595
+
596
+ %newStackPointer = extractvalue %Memory %newMemory, 0
597
+ call void @shareFrames(%StackPointer %newStackPointer)
598
+
599
+ %newRegion = call %Region @copyRegion(%Region %region)
600
+
601
+ store %ReferenceCount 0, ptr %newStackReferenceCount
602
+ store %Memory %newMemory, ptr %newStackMemory
603
+ store %Region %newRegion, ptr %newStackRegion
604
+ store %Prompt %prompt, ptr %newStackPrompt
605
+
606
+ %isNull = icmp eq %Stack %rest, null
607
+ br i1 %isNull, label %stop, label %next
608
+
609
+ next:
610
+ %nextNew = call ptr @malloc(i64 120)
611
+ store %Stack %nextNew, ptr %newStackRest
612
+ br label %loop
613
+
614
+ stop:
615
+ store %Stack null, ptr %newStackRest
616
+ ret %Stack %newHead
617
+ }
618
+
619
+ define void @shareStack(%Stack %stack) alwaysinline {
620
+ %stackReferenceCount = getelementptr %StackValue, %Stack %stack, i64 0, i32 0
621
+ %referenceCount = load %ReferenceCount, ptr %stackReferenceCount
622
+ %referenceCount.1 = add %ReferenceCount %referenceCount, 1
623
+ store %ReferenceCount %referenceCount.1, ptr %stackReferenceCount
624
+ ret void
625
+ }
626
+
627
+ define void @eraseStack(%Stack %stack) alwaysinline {
628
+ %stackReferenceCount = getelementptr %StackValue, %Stack %stack, i64 0, i32 0
629
+ %referenceCount = load %ReferenceCount, ptr %stackReferenceCount
630
+ switch %ReferenceCount %referenceCount, label %decr [%ReferenceCount 0, label %free]
631
+
632
+ decr:
633
+ %referenceCount.1 = sub %ReferenceCount %referenceCount, 1
634
+ store %ReferenceCount %referenceCount.1, ptr %stackReferenceCount
635
+ ret void
636
+
637
+ free:
638
+ %stackStackPointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 0
639
+ %stackRegion = getelementptr %StackValue, %Stack %stack, i64 0, i32 2
640
+ %stackRest = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
641
+
642
+ %stackPointer = load %StackPointer, ptr %stackStackPointer
643
+ %region = load %Region, ptr %stackRegion
644
+ %rest = load %Stack, ptr %stackRest
645
+
646
+ call void @free(%Stack %stack)
647
+ call void @eraseFrames(%StackPointer %stackPointer)
648
+ call void @eraseRegion(%Region %region)
649
+
650
+ %isNull = icmp eq %Stack %rest, null
651
+ br i1 %isNull, label %done, label %next
652
+
653
+ next:
654
+ call void @eraseStack(%Stack %rest)
655
+ ret void
656
+
657
+ done:
658
+ ret void
659
+ }
660
+
661
+ define void @shareFrames(%StackPointer %stackPointer) alwaysinline {
662
+ %newStackPointer = getelementptr %FrameHeader, %StackPointer %stackPointer, i64 -1
663
+ %stackSharer = getelementptr %FrameHeader, %StackPointer %newStackPointer, i64 0, i32 1
664
+ %sharer = load %Sharer, ptr %stackSharer
665
+ tail call void %sharer(%StackPointer %newStackPointer)
666
+ ret void
667
+ }
668
+
669
+ define void @eraseFrames(%StackPointer %stackPointer) alwaysinline {
670
+ %newStackPointer = getelementptr %FrameHeader, %StackPointer %stackPointer, i64 -1
671
+ %stackEraser = getelementptr %FrameHeader, %StackPointer %newStackPointer, i64 0, i32 2
672
+ %eraser = load %Eraser, ptr %stackEraser
673
+ tail call void %eraser(%StackPointer %newStackPointer)
674
+ ret void
675
+ }
676
+
677
+ ; RTS initialization
678
+
679
+ define tailcc void @topLevel(%Pos %val, %Stack %stack) {
680
+ %rest = call %Stack @underflowStack(%Stack %stack)
681
+ ; assert %rest == null
682
+ ret void
683
+ }
684
+
685
+ define void @topLevelSharer(%Environment %environment) {
686
+ ; TODO this should never be called
687
+ ret void
688
+ }
689
+
690
+ define void @topLevelEraser(%Environment %environment) {
691
+ ; TODO this should never be called
692
+ ret void
693
+ }
694
+
695
+ define %Stack @withEmptyStack() {
696
+ ; TODO all stacks share the same source of fresh prompts
697
+ %prompt = call %Prompt @freshPrompt()
698
+ %stack = call %Stack @newStack(%Prompt %prompt)
699
+
700
+ %stackStackPointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 0
701
+ %stackPointer = load %StackPointer, ptr %stackStackPointer
702
+
703
+ %returnAddressPointer = getelementptr %FrameHeader, %StackPointer %stackPointer, i64 0, i32 0
704
+ %sharerPointer = getelementptr %FrameHeader, %StackPointer %stackPointer, i64 0, i32 1
705
+ %eraserPointer = getelementptr %FrameHeader, %StackPointer %stackPointer, i64 0, i32 2
706
+
707
+ store %ReturnAddress @topLevel, ptr %returnAddressPointer
708
+ store %Sharer @topLevelSharer, ptr %sharerPointer
709
+ store %Eraser @topLevelEraser, ptr %eraserPointer
710
+
711
+ %stackPointer_2 = getelementptr %FrameHeader, %StackPointer %stackPointer, i64 1
712
+ store %StackPointer %stackPointer_2, ptr %stackStackPointer
713
+
714
+ ret %Stack %stack
715
+ }
716
+
717
+ define void @run_i64(%Neg %f, i64 %arg) {
718
+ ; fresh stack
719
+ %stack = call %Stack @withEmptyStack()
720
+
721
+ ; prepare call
722
+ %arrayPointer = extractvalue %Neg %f, 0
723
+ %object = extractvalue %Neg %f, 1
724
+ %functionPointerPointer = getelementptr ptr, ptr %arrayPointer, i64 0
725
+ %functionPointer = load ptr, ptr %functionPointerPointer
726
+
727
+ ; call
728
+ tail call tailcc %Pos %functionPointer(%Object %object, i64 %arg, %Stack %stack)
729
+ ret void
730
+ }
731
+
732
+
733
+ define void @run_Pos(%Neg %f, %Pos %arg) {
734
+ ; fresh stack
735
+ %stack = call %Stack @withEmptyStack()
736
+
737
+ ; prepare call
738
+ %arrayPointer = extractvalue %Neg %f, 0
739
+ %object = extractvalue %Neg %f, 1
740
+ %functionPointerPointer = getelementptr ptr, ptr %arrayPointer, i64 0
741
+ %functionPointer = load ptr, ptr %functionPointerPointer
742
+
743
+ ; call
744
+ tail call tailcc %Pos %functionPointer(%Object %object, %Pos %arg, %Stack %stack)
745
+ ret void
746
+ }
747
+
748
+ define void @run(%Neg %f) {
749
+ ; fresh stack
750
+ %stack = call %Stack @withEmptyStack()
751
+
752
+ ; prepare call
753
+ %arrayPointer = extractvalue %Neg %f, 0
754
+ %object = extractvalue %Neg %f, 1
755
+ %functionPointerPointer = getelementptr ptr, ptr %arrayPointer, i64 0
756
+ %functionPointer = load ptr, ptr %functionPointerPointer
757
+
758
+ ; call
759
+ tail call tailcc %Pos %functionPointer(%Object %object, %Stack %stack)
760
+ ret void
761
+ }