@effekt-lang/effekt 0.5.0 → 0.7.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.
@@ -66,20 +66,23 @@
66
66
  ;
67
67
  %Region = type [ 3 x %Memory ]
68
68
 
69
+ ; Unique address for each handler.
70
+ %Prompt = type ptr
71
+
72
+ ; A Continuation capturing a list of stacks.
73
+ ; This points to the last element in a cyclic linked list of StackValues
74
+ %Resumption = type ptr
75
+
69
76
  ; The "meta" stack (a stack of stacks) -- a pointer to a %StackValue
70
77
  %Stack = type ptr
71
78
 
72
- ; Unique tags to index into the stack.
73
- %Prompt = type i64
74
-
75
- ; fresh prompt generation
76
- @lastPrompt = private global %Prompt 0
79
+ ; Lives in a stable address
80
+ %PromptValue = type { %ReferenceCount, %Stack }
77
81
 
78
82
  ; This is used for two purposes:
79
83
  ; - a refied first-class list of stacks (cyclic linked-list)
80
84
  ; - as part of an intrusive linked-list of stacks (meta stack)
81
- %StackValue = type { %ReferenceCount, %Memory, %Region, %Prompt, %Stack }
82
-
85
+ %StackValue = type { %ReferenceCount, %Memory, %Region, %Prompt, i1, %Stack }
83
86
 
84
87
 
85
88
 
@@ -89,8 +92,8 @@
89
92
  ; Negative types (codata) consist of a vtable and a heap object
90
93
  %Neg = type {ptr, %Object}
91
94
 
92
- ; Reference into an arena (prompt -- cast to 32bit, offset 32bit)
93
- %Reference = type {i32, i32}
95
+ ; Reference to a mutable variable (prompt, offset)
96
+ %Reference = type { %Prompt, i64 }
94
97
 
95
98
  ; Builtin Types
96
99
 
@@ -127,17 +130,17 @@ define private %Prompt @currentPrompt(%Stack %stack) {
127
130
  }
128
131
 
129
132
  define private %Prompt @freshPrompt() {
130
- %currentPrompt = load %Prompt, ptr @lastPrompt
131
- %newPrompt = add %Prompt %currentPrompt, 1
132
- store %Prompt %newPrompt, ptr @lastPrompt
133
- ret %Prompt %newPrompt
133
+ %promptSize = ptrtoint ptr getelementptr (%PromptValue, ptr null, i64 1) to i64
134
+ %prompt = call %Prompt @malloc(i64 %promptSize)
135
+ store %PromptValue zeroinitializer, %Prompt %prompt
136
+ ret %Prompt %prompt
134
137
  }
135
138
 
136
139
  ; Garbage collection
137
140
 
138
141
  define private %Object @newObject(%Eraser %eraser, i64 %environmentSize) alwaysinline {
139
- ; This magical 16 is the size of the object header
140
- %size = add i64 %environmentSize, 16
142
+ %headerSize = ptrtoint ptr getelementptr (%Header, ptr null, i64 1) to i64
143
+ %size = add i64 %environmentSize, %headerSize
141
144
  %object = call ptr @malloc(i64 %size)
142
145
  %objectReferenceCount = getelementptr %Header, ptr %object, i64 0, i32 0
143
146
  %objectEraser = getelementptr %Header, ptr %object, i64 0, i32 1
@@ -219,26 +222,15 @@ define void @eraseNegative(%Neg %val) alwaysinline {
219
222
 
220
223
 
221
224
  ; Arena management
222
- define private ptr @getRegionPointer(%Prompt %prompt, %Stack %stack) {
223
- entry:
224
- %prompt_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 3
225
- %currentPrompt = load %Prompt, ptr %prompt_pointer
226
- %promptMatch = icmp eq %Prompt %currentPrompt, %prompt
227
- br i1 %promptMatch, label %found, label %continue
228
-
229
- continue:
230
- %nextStack_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
231
- %nextStack = load %Stack, ptr %nextStack_pointer
232
- %region = tail call ptr @getRegionPointer(%Prompt %prompt, %Stack %nextStack)
233
- ret ptr %region
234
-
235
- found:
236
- %stackRegion = getelementptr %StackValue, %Stack %stack, i64 0, i32 2
237
- ret ptr %stackRegion
225
+ define private ptr @getRegionPointer(%Prompt %prompt) {
226
+ %stack_pointer = getelementptr %PromptValue, %Prompt %prompt, i64 0, i32 1
227
+ %stack = load %Stack, ptr %stack_pointer
228
+ %region_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 2
229
+ ret ptr %region_pointer
238
230
  }
239
231
 
240
- define private { ptr, %Reference } @alloc(i64 %index, %Prompt %prompt, %Stack %stack) alwaysinline {
241
- %region_pointer = call ptr @getRegionPointer(%Prompt %prompt, %Stack %stack)
232
+ define private { ptr, %Reference } @alloc(i64 %index, %Prompt %prompt) alwaysinline {
233
+ %region_pointer = call ptr @getRegionPointer(%Prompt %prompt)
242
234
 
243
235
  %stackPointer_pointer = getelementptr %Region, ptr %region_pointer, i64 0, i64 %index, i32 0
244
236
  %base_pointer = getelementptr %Region, ptr %region_pointer, i64 0, i64 %index, i32 1
@@ -260,16 +252,12 @@ continue:
260
252
  store %StackPointer %nextStackPointer, ptr %stackPointer_pointer
261
253
  %intBase = ptrtoint %Base %base to i64
262
254
  %intStackPointer = ptrtoint %StackPointer %stackPointer to i64
263
- %offset64 = sub i64 %intStackPointer, %intBase
264
-
265
- %prompt32 = trunc i64 %prompt to i32
266
- %offset32 = trunc i64 %offset64 to i32
255
+ %offset = sub i64 %intStackPointer, %intBase
267
256
 
268
257
  %ret.0 = insertvalue { ptr, %Reference } undef, %StackPointer %stackPointer, 0
269
- %ref.1 = insertvalue %Reference undef, i32 %prompt32, 0
270
- %ref.2 = insertvalue %Reference %ref.1, i32 %offset32, 1
271
- %ret.1 = insertvalue { ptr, %Reference } %ret.0, %Reference %ref.2, 1
272
- ret { ptr, %Reference } %ret.1
258
+ %ret.1 = insertvalue { ptr, %Reference } %ret.0, %Prompt %prompt, 1, 0
259
+ %ret.2 = insertvalue { ptr, %Reference } %ret.1, i64 %offset, 1, 1
260
+ ret { ptr, %Reference } %ret.2
273
261
 
274
262
  realloc:
275
263
  %intBase_2 = ptrtoint %Base %base to i64
@@ -288,77 +276,57 @@ realloc:
288
276
  store %Limit %newlimit, ptr %limit_pointer
289
277
  store %StackPointer %newNextStackPointer, ptr %stackPointer_pointer
290
278
 
291
- %prompt32_2 = trunc i64 %prompt to i32
292
- %arenaSize32 = trunc i64 %arenaSize to i32
293
-
294
279
  %ret..0 = insertvalue { ptr, %Reference } undef, %StackPointer %newStackPointer, 0
295
- %ref..1 = insertvalue %Reference undef, i32 %prompt32_2, 0
296
- %ref..2 = insertvalue %Reference %ref..1, i32 %arenaSize32, 1
297
- %ret..1 = insertvalue { ptr, %Reference } %ret..0, %Reference %ref..2, 1
298
- ret { ptr, %Reference } %ret..1
280
+ %ret..1 = insertvalue { ptr, %Reference } %ret..0, %Prompt %prompt, 1, 0
281
+ %ret..2 = insertvalue { ptr, %Reference } %ret..1, i64 %arenaSize, 1, 1
282
+ ret { ptr, %Reference } %ret..2
299
283
  }
300
284
 
301
285
 
302
286
  define private ptr @getPointer(%Reference %reference, i64 %index, %Stack %stack) {
303
- %prompt32 = extractvalue %Reference %reference, 0
304
- %offset32 = extractvalue %Reference %reference, 1
305
- %prompt = zext i32 %prompt32 to i64
306
- %offset = zext i32 %offset32 to i64
287
+ %prompt = extractvalue %Reference %reference, 0
288
+ %offset = extractvalue %Reference %reference, 1
307
289
 
308
- %region_pointer = call ptr @getRegionPointer(%Prompt %prompt, %Stack %stack)
290
+ %region_pointer = call ptr @getRegionPointer(%Prompt %prompt)
309
291
  %base_pointer = getelementptr %Region, ptr %region_pointer, i64 0, i64 %index, i32 1
310
292
  %base = load %Base, ptr %base_pointer
311
293
  %pointer = getelementptr i8, ptr %base, i64 %offset
312
294
  ret ptr %pointer
313
295
  }
314
296
 
315
- define private %Stack @getStack(%Stack %stack, %Prompt %prompt) {
316
- %promptPointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 3
317
- %thisPrompt = load %Prompt, ptr %promptPointer
318
- %found = icmp eq %Prompt %prompt, %thisPrompt
319
- br i1 %found, label %done, label %recurse
320
-
321
- done:
297
+ define private %Stack @getStack(%Prompt %prompt) {
298
+ %stack_pointer = getelementptr %PromptValue, %Prompt %prompt, i64 0, i32 1
299
+ %stack = load %Stack, ptr %stack_pointer
322
300
  ret %Stack %stack
323
-
324
- recurse:
325
- %nextStackPointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
326
- %nextStack = load %Stack, ptr %nextStackPointer
327
- %result = call %Stack @getStack(%Stack %nextStack, %Prompt %prompt)
328
- ret %Stack %result
329
301
  }
330
302
 
331
303
  define private ptr @getVarPointer(%Reference %reference, %Stack %stack) {
332
- %prompt32 = extractvalue %Reference %reference, 0
333
- %offset32 = extractvalue %Reference %reference, 1
334
- %prompt = zext i32 %prompt32 to i64
335
- %offset = zext i32 %offset32 to i64
336
-
337
- %targetStack = call %Stack @getStack(%Stack %stack, %Prompt %prompt)
338
- %basePointer = getelementptr %StackValue, %Stack %targetStack, i64 0, i32 1, i32 1
339
- %base = load %Base, ptr %basePointer
304
+ %prompt = extractvalue %Reference %reference, 0
305
+ %offset = extractvalue %Reference %reference, 1
306
+
307
+ %targetStack = call %Stack @getStack(%Prompt %prompt)
308
+ %base_pointer = getelementptr %StackValue, %Stack %targetStack, i64 0, i32 1, i32 1
309
+ %base = load %Base, ptr %base_pointer
340
310
  %varPointer = getelementptr i8, %Base %base, i64 %offset
341
311
  ret ptr %varPointer
342
312
  }
343
313
 
344
314
  define private %Reference @newReference(%Stack %stack) alwaysinline {
345
- %stackPointerPointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 0
346
- %basePointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 1
315
+ %stackPointer_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 0
316
+ %base_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 1
347
317
 
348
- %stackPointer = load %StackPointer, ptr %stackPointerPointer
349
- %base = load %StackPointer, ptr %basePointer
318
+ %stackPointer = load %StackPointer, ptr %stackPointer_pointer
319
+ %base = load %StackPointer, ptr %base_pointer
350
320
 
351
321
  %intStack = ptrtoint %StackPointer %stackPointer to i64
352
322
  %intBase = ptrtoint %StackPointer %base to i64
353
323
 
354
324
  %offset = sub i64 %intStack, %intBase
355
- %offset32 = trunc i64 %offset to i32
356
325
 
357
326
  %prompt = call %Prompt @currentPrompt(%Stack %stack)
358
- %prompt32 = trunc %Prompt %prompt to i32
359
327
 
360
- %reference..1 = insertvalue %Reference undef, i32 %prompt32, 0
361
- %reference = insertvalue %Reference %reference..1, i32 %offset32, 1
328
+ %reference..1 = insertvalue %Reference undef, %Prompt %prompt, 0
329
+ %reference = insertvalue %Reference %reference..1, i64 %offset, 1
362
330
 
363
331
  ret %Reference %reference
364
332
  }
@@ -366,30 +334,67 @@ define private %Reference @newReference(%Stack %stack) alwaysinline {
366
334
  ; Stack management
367
335
 
368
336
  define private %StackPointer @stackAllocate(%Stack %stack, i64 %n) {
369
- %stackStackPointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 0
370
- %stackPointer = load %StackPointer, ptr %stackStackPointer
337
+ %stackPointer_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 0
338
+ %limit_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 2
371
339
 
372
- %stackPointer_2 = getelementptr i8, %StackPointer %stackPointer, i64 %n
373
- store %StackPointer %stackPointer_2, ptr %stackStackPointer
374
- ret %StackPointer %stackPointer
340
+ %currentStackPointer = load %StackPointer, ptr %stackPointer_pointer
341
+ %limit = load %Limit, ptr %limit_pointer
342
+
343
+ %nextStackPointer = getelementptr i8, %StackPointer %currentStackPointer, i64 %n
344
+ %isInside = icmp ule %StackPointer %nextStackPointer, %limit
345
+ br i1 %isInside, label %continue, label %realloc
346
+
347
+ continue:
348
+ store %StackPointer %nextStackPointer, ptr %stackPointer_pointer
349
+ ret %StackPointer %currentStackPointer
350
+
351
+ realloc:
352
+ %base_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 1
353
+ %base = load %Base, ptr %base_pointer
354
+
355
+ %intStackPointer = ptrtoint %StackPointer %currentStackPointer to i64
356
+ %intBase = ptrtoint %Base %base to i64
357
+
358
+ %size = sub i64 %intStackPointer, %intBase
359
+ %nextSize = add i64 %size, %n
360
+ %newSize = call i64 @nextPowerOfTwo(i64 %nextSize)
361
+
362
+ %newBase = call ptr @realloc(ptr %base, i64 %newSize)
363
+ %newLimit = getelementptr i8, %Base %newBase, i64 %newSize
364
+ %newStackPointer = getelementptr i8, %Base %newBase, i64 %size
365
+ %newNextStackPointer = getelementptr i8, %StackPointer %newStackPointer, i64 %n
366
+
367
+ store %StackPointer %newNextStackPointer, ptr %stackPointer_pointer
368
+ store %Base %newBase, ptr %base_pointer
369
+ store %Limit %newLimit, ptr %limit_pointer
370
+
371
+ ret %StackPointer %newStackPointer
375
372
  }
376
373
 
377
374
  define private %StackPointer @stackDeallocate(%Stack %stack, i64 %n) {
378
- %stackStackPointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 0
379
- %stackPointer = load %StackPointer, ptr %stackStackPointer
375
+ %stackPointer_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 0
376
+ %stackPointer = load %StackPointer, ptr %stackPointer_pointer
380
377
 
381
378
  %o = sub i64 0, %n
382
- %stackPointer_2 = getelementptr i8, %StackPointer %stackPointer, i64 %o
383
- store %StackPointer %stackPointer_2, ptr %stackStackPointer
379
+ %newStackPointer = getelementptr i8, %StackPointer %stackPointer, i64 %o
380
+ store %StackPointer %newStackPointer, ptr %stackPointer_pointer
384
381
 
385
- ret %StackPointer %stackPointer_2
382
+ ret %StackPointer %newStackPointer
383
+ }
384
+
385
+ define i64 @nextPowerOfTwo(i64 %x) {
386
+ %leadingZeros = call i64 @llvm.ctlz.i64(i64 %x, i1 false)
387
+ %numBits = sub i64 64, %leadingZeros
388
+ %result = shl i64 1, %numBits
389
+ ret i64 %result
386
390
  }
387
391
 
388
392
  ; Meta-stack management
389
393
 
390
394
  define private %Memory @newMemory() {
391
- %stackPointer = call %StackPointer @malloc(i64 268435456)
392
- %limit = getelementptr i8, ptr %stackPointer, i64 268435456
395
+ %size = shl i64 1, 6
396
+ %stackPointer = call %StackPointer @malloc(i64 %size)
397
+ %limit = getelementptr i8, ptr %stackPointer, i64 %size
393
398
 
394
399
  %memory.0 = insertvalue %Memory undef, %StackPointer %stackPointer, 0
395
400
  %memory.1 = insertvalue %Memory %memory.0, %Base %stackPointer, 1
@@ -398,58 +403,101 @@ define private %Memory @newMemory() {
398
403
  ret %Memory %memory.2
399
404
  }
400
405
 
401
- define private %Stack @newStack(%Prompt %prompt) {
406
+ define private %Stack @reset(%Stack %oldStack) {
407
+
408
+ %prompt = call %Prompt @freshPrompt()
409
+
410
+ %size = ptrtoint ptr getelementptr (%StackValue, ptr null, i64 1) to i64
411
+ %stack = call ptr @malloc(i64 %size)
402
412
 
403
- ; TODO find actual size of stack
404
- %stack = call ptr @malloc(i64 120)
405
413
 
406
- ; TODO initialize to zero and grow later
407
414
  %stackMemory = call %Memory @newMemory()
408
415
 
409
- %stack.0 = insertvalue %StackValue undef, %ReferenceCount 0, 0
410
- %stack.1 = insertvalue %StackValue %stack.0, %Memory %stackMemory, 1
411
- %stack.2 = insertvalue %StackValue %stack.1, %Region zeroinitializer, 2
412
- %stack.3 = insertvalue %StackValue %stack.2, %Prompt %prompt, 3
413
- %stack.4 = insertvalue %StackValue %stack.3, %Stack zeroinitializer, 4
416
+ %stack.0 = insertvalue %StackValue zeroinitializer, %Memory %stackMemory, 1
417
+ %stack.1 = insertvalue %StackValue %stack.0, %Prompt %prompt, 3
418
+ %stack.2 = insertvalue %StackValue %stack.1, %Stack %oldStack, 5
419
+
420
+ store %StackValue %stack.2, %Stack %stack
414
421
 
415
- store %StackValue %stack.4, %Stack %stack
422
+ %stack_pointer = getelementptr %PromptValue, %Prompt %prompt, i64 0, i32 1
423
+ store %Stack %stack, ptr %stack_pointer
416
424
 
417
425
  ret %Stack %stack
418
426
  }
419
427
 
420
- define private void @pushStack(%Stack %stack, %Stack %oldStack) {
421
- %stackRest = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
422
- %rest = load %Stack, ptr %stackRest
423
- %isNull = icmp eq %Stack %rest, null
424
- br i1 %isNull, label %done, label %next
428
+ define private void @updatePrompts(%Stack %stack) {
429
+ %dirtyBit_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
430
+ %dirtyBit = load i1, ptr %dirtyBit_pointer
431
+ br i1 %dirtyBit, label %continue, label %done
425
432
 
426
433
  done:
427
- store %Stack %oldStack, ptr %stackRest
428
434
  ret void
429
435
 
430
- next:
431
- tail call void @pushStack(%Stack %rest, %Stack %oldStack)
436
+ continue:
437
+ %prompt_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 3
438
+ %prompt = load %Prompt, ptr %prompt_pointer
439
+ %stack_pointer = getelementptr %PromptValue, %Prompt %prompt, i64 0, i32 1
440
+ %promptStack = load %Stack, ptr %stack_pointer
441
+ %isOccupied = icmp ne %Stack %promptStack, null
442
+ br i1 %isOccupied, label %displace, label %update
443
+
444
+ displace:
445
+ call void @displace(%Stack %promptStack)
446
+ br label %update
447
+
448
+ update:
449
+ store %Stack %stack, ptr %stack_pointer
450
+ store i1 0, ptr %dirtyBit_pointer
451
+
452
+ %next_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 5
453
+ %next = load %Stack, ptr %next_pointer
454
+ tail call void @updatePrompts(%Stack %next)
432
455
  ret void
433
456
  }
434
457
 
435
- define private %Stack @popStacks(%Stack %stack, %Prompt %prompt) {
436
- entry:
458
+ define void @displace(%Stack %stack) {
437
459
  %prompt_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 3
438
- %currentPrompt = load %Prompt, ptr %prompt_pointer
439
- %promptMatch = icmp eq %Prompt %currentPrompt, %prompt
440
- br i1 %promptMatch, label %found, label %continue
460
+ %next_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 5
461
+ %dirtyBit_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
462
+ %dirtyBit = load i1, ptr %dirtyBit_pointer
463
+ br i1 %dirtyBit, label %done, label %continue
464
+
465
+ done:
466
+ ret void
441
467
 
442
468
  continue:
443
- %nextStack_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
444
- %nextStack = load %Stack, ptr %nextStack_pointer
445
- %result = tail call %Stack @popStacks(%Stack %nextStack, %Prompt %prompt)
446
- ret %Stack %result
469
+ %prompt = load %Prompt, ptr %prompt_pointer
470
+ %stack_pointer = getelementptr %PromptValue, %Prompt %prompt, i64 0, i32 1
471
+ store %Stack null, ptr %stack_pointer
472
+ store i1 1, ptr %dirtyBit_pointer
447
473
 
448
- found:
449
- %nextStack2_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
450
- %nextStack2 = load %Stack, ptr %nextStack2_pointer
451
- store %Stack null, ptr %nextStack2_pointer
452
- ret %Stack %nextStack2
474
+ %next = load %Stack, ptr %next_pointer
475
+ tail call void @displace(%Stack %next)
476
+ ret void
477
+ }
478
+
479
+ define %Stack @resume(%Resumption %resumption, %Stack %oldStack) {
480
+ %uniqueResumption = call %Resumption @uniqueStack(%Resumption %resumption)
481
+ %rest_pointer = getelementptr %StackValue, %Resumption %uniqueResumption, i64 0, i32 5
482
+ %start = load %Stack, ptr %rest_pointer
483
+ call void @updatePrompts(%Stack %start)
484
+
485
+ store %Stack %oldStack, ptr %rest_pointer
486
+
487
+ ret %Stack %start
488
+ }
489
+
490
+ define private {%Resumption, %Stack} @shift(%Stack %stack, %Prompt %prompt) {
491
+ %resumpion_pointer = getelementptr %PromptValue, %Prompt %prompt, i64 0, i32 1
492
+ %resumption = load %Stack, ptr %resumpion_pointer
493
+ %next_pointer = getelementptr %StackValue, %Stack %resumption, i64 0, i32 5
494
+ %next = load %Stack, ptr %next_pointer
495
+
496
+ store %Stack %stack, ptr %next_pointer
497
+
498
+ %result.0 = insertvalue {%Resumption, %Stack} undef, %Resumption %resumption, 0
499
+ %result = insertvalue {%Resumption, %Stack} %result.0, %Stack %next, 1
500
+ ret {%Resumption, %Stack} %result
453
501
  }
454
502
 
455
503
  define private void @eraseMemory(%Memory %memory) {
@@ -491,17 +539,53 @@ define private void @eraseRegion(%Region %region) alwaysinline {
491
539
  ret void
492
540
  }
493
541
 
542
+ define void @erasePrompt(%Prompt %prompt, i1 %dirtyBit) alwaysinline {
543
+ br i1 %dirtyBit, label %continue, label %clearPrompt
544
+
545
+ clearPrompt:
546
+ %stack_pointer = getelementptr %PromptValue, %Prompt %prompt, i64 0, i32 1
547
+ store %Stack null, ptr %stack_pointer
548
+ br label %continue
549
+
550
+ continue:
551
+ %referenceCount_pointer = getelementptr %PromptValue, %Prompt %prompt, i64 0, i32 0
552
+ %referenceCount = load %ReferenceCount, ptr %referenceCount_pointer
553
+ switch %ReferenceCount %referenceCount, label %decrement [%ReferenceCount 0, label %free]
554
+
555
+ decrement:
556
+ %newReferenceCount = sub %ReferenceCount %referenceCount, 1
557
+ store %ReferenceCount %newReferenceCount, ptr %referenceCount_pointer
558
+ ret void
559
+
560
+ free:
561
+ call void @free(%Prompt %prompt)
562
+ ret void
563
+ }
564
+
565
+ define void @sharePrompt(%Prompt %prompt) alwaysinline {
566
+ %referenceCount_pointer = getelementptr %PromptValue, %Prompt %prompt, i64 0, i32 0
567
+ %referenceCount = load %ReferenceCount, ptr %referenceCount_pointer
568
+ %newReferenceCount = add %ReferenceCount %referenceCount, 1
569
+ store %ReferenceCount %newReferenceCount, ptr %referenceCount_pointer
570
+ ret void
571
+ }
572
+
494
573
  define private %Stack @underflowStack(%Stack %stack) {
495
574
  %stackMemory = getelementptr %StackValue, %Stack %stack, i64 0, i32 1
496
575
  %stackRegion = getelementptr %StackValue, %Stack %stack, i64 0, i32 2
497
- %stackRest = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
576
+ %stackPrompt = getelementptr %StackValue, %Stack %stack, i64 0, i32 3
577
+ %stackDirtyBit = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
578
+ %stackRest = getelementptr %StackValue, %Stack %stack, i64 0, i32 5
498
579
 
499
580
  %memory = load %Memory, ptr %stackMemory
500
581
  %region = load %Region, ptr %stackRegion
582
+ %prompt = load %Prompt, ptr %stackPrompt
501
583
  %rest = load %Stack, ptr %stackRest
584
+ %dirtyBit = load i1, ptr %stackDirtyBit
502
585
 
503
586
  call void @eraseMemory(%Memory %memory)
504
587
  call void @eraseRegion(%Region %region)
588
+ call void @erasePrompt(%Prompt %prompt, i1 false)
505
589
  call void @free(%Stack %stack)
506
590
 
507
591
  ret %Stack %rest
@@ -558,21 +642,25 @@ define private %Region @copyRegion(%Region %region) alwaysinline {
558
642
  ret %Region %region.2
559
643
  }
560
644
 
561
- define private %Stack @uniqueStack(%Stack %stack) alwaysinline {
645
+ define private %Resumption @uniqueStack(%Resumption %resumption) alwaysinline {
562
646
 
563
647
  entry:
564
- %stackReferenceCount = getelementptr %StackValue, %Stack %stack, i64 0, i32 0
565
- %referenceCount = load %ReferenceCount, ptr %stackReferenceCount
648
+ %referenceCount_pointer = getelementptr %StackValue, %Resumption %resumption, i64 0, i32 0
649
+ %referenceCount = load %ReferenceCount, ptr %referenceCount_pointer
566
650
  switch %ReferenceCount %referenceCount, label %copy [%ReferenceCount 0, label %done]
567
651
 
568
652
  done:
569
- ret %Stack %stack
653
+ ret %Resumption %resumption
570
654
 
571
655
  copy:
572
656
  %newOldReferenceCount = sub %ReferenceCount %referenceCount, 1
573
- store %ReferenceCount %newOldReferenceCount, ptr %stackReferenceCount
657
+ store %ReferenceCount %newOldReferenceCount, ptr %referenceCount_pointer
658
+ %stack_pointer = getelementptr %StackValue, %Resumption %resumption, i64 0, i32 5
659
+ %stack = load %Stack, ptr %stack_pointer
660
+
661
+ %size = ptrtoint ptr getelementptr (%StackValue, ptr null, i64 1) to i64
662
+ %newHead = call ptr @malloc(i64 %size)
574
663
 
575
- %newHead = call ptr @malloc(i64 120)
576
664
  br label %loop
577
665
 
578
666
  loop:
@@ -582,18 +670,19 @@ loop:
582
670
  %stackMemory = getelementptr %StackValue, %Stack %old, i64 0, i32 1
583
671
  %stackRegion = getelementptr %StackValue, %Stack %old, i64 0, i32 2
584
672
  %stackPrompt = getelementptr %StackValue, %Stack %old, i64 0, i32 3
585
- %stackRest = getelementptr %StackValue, %Stack %old, i64 0, i32 4
673
+ %stackRest = getelementptr %StackValue, %Stack %old, i64 0, i32 5
586
674
 
587
675
  %memory = load %Memory, ptr %stackMemory
588
676
  %region = load %Region, ptr %stackRegion
589
677
  %prompt = load %Prompt, ptr %stackPrompt
590
678
  %rest = load %Stack, ptr %stackRest
591
679
 
592
- %newStackReferenceCount = getelementptr %StackValue, %Stack %newStack, i64 0, i32 0
680
+ %newStackReferenceCounter = getelementptr %StackValue, %Stack %newStack, i64 0, i32 0
593
681
  %newStackMemory = getelementptr %StackValue, %Stack %newStack, i64 0, i32 1
594
682
  %newStackRegion = getelementptr %StackValue, %Stack %newStack, i64 0, i32 2
595
683
  %newStackPrompt = getelementptr %StackValue, %Stack %newStack, i64 0, i32 3
596
- %newStackRest = getelementptr %StackValue, %Stack %newStack, i64 0, i32 4
684
+ %newStackDirtyBit = getelementptr %StackValue, %Stack %newStack, i64 0, i32 4
685
+ %newStackRest = getelementptr %StackValue, %Stack %newStack, i64 0, i32 5
597
686
 
598
687
  %newMemory = call %Memory @copyMemory(%Memory %memory)
599
688
 
@@ -602,54 +691,70 @@ loop:
602
691
 
603
692
  %newRegion = call %Region @copyRegion(%Region %region)
604
693
 
605
- store %ReferenceCount 0, ptr %newStackReferenceCount
694
+ call void @sharePrompt(%Prompt %prompt)
695
+
696
+ store i64 0, ptr %newStackReferenceCounter
606
697
  store %Memory %newMemory, ptr %newStackMemory
607
698
  store %Region %newRegion, ptr %newStackRegion
608
699
  store %Prompt %prompt, ptr %newStackPrompt
700
+ store i1 1, ptr %newStackDirtyBit
609
701
 
610
- %isNull = icmp eq %Stack %rest, null
611
- br i1 %isNull, label %stop, label %next
702
+ %isEnd = icmp eq %Stack %old, %resumption
703
+ br i1 %isEnd, label %stop, label %next
612
704
 
613
705
  next:
614
- %nextNew = call ptr @malloc(i64 120)
706
+ %nextNew = call ptr @malloc(i64 %size)
615
707
  store %Stack %nextNew, ptr %newStackRest
616
708
  br label %loop
617
709
 
618
710
  stop:
619
- store %Stack null, ptr %newStackRest
620
- ret %Stack %newHead
711
+ store %Stack %newHead, ptr %newStackRest
712
+ ret %Stack %newStack
621
713
  }
622
714
 
623
- define void @shareStack(%Stack %stack) alwaysinline {
624
- %stackReferenceCount = getelementptr %StackValue, %Stack %stack, i64 0, i32 0
625
- %referenceCount = load %ReferenceCount, ptr %stackReferenceCount
715
+ define void @shareResumption(%Resumption %resumption) alwaysinline {
716
+ %referenceCount_pointer = getelementptr %StackValue, %Resumption %resumption, i64 0, i32 0
717
+ %referenceCount = load %ReferenceCount, ptr %referenceCount_pointer
626
718
  %referenceCount.1 = add %ReferenceCount %referenceCount, 1
627
- store %ReferenceCount %referenceCount.1, ptr %stackReferenceCount
719
+ store %ReferenceCount %referenceCount.1, ptr %referenceCount_pointer
628
720
  ret void
629
721
  }
630
722
 
631
- define void @eraseStack(%Stack %stack) alwaysinline {
632
- %stackReferenceCount = getelementptr %StackValue, %Stack %stack, i64 0, i32 0
633
- %referenceCount = load %ReferenceCount, ptr %stackReferenceCount
723
+ define void @eraseResumption(%Resumption %resumption) alwaysinline {
724
+ %referenceCount_pointer = getelementptr %StackValue, %Resumption %resumption, i64 0, i32 0
725
+ %referenceCount = load %ReferenceCount, ptr %referenceCount_pointer
634
726
  switch %ReferenceCount %referenceCount, label %decr [%ReferenceCount 0, label %free]
635
727
 
636
728
  decr:
637
729
  %referenceCount.1 = sub %ReferenceCount %referenceCount, 1
638
- store %ReferenceCount %referenceCount.1, ptr %stackReferenceCount
730
+ store %ReferenceCount %referenceCount.1, ptr %referenceCount_pointer
639
731
  ret void
640
732
 
641
733
  free:
642
- %stackStackPointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 0
643
- %stackRegion = getelementptr %StackValue, %Stack %stack, i64 0, i32 2
644
- %stackRest = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
734
+ %stack_pointer = getelementptr %StackValue, %Resumption %resumption, i64 0, i32 5
735
+ %stack = load %Stack, ptr %stack_pointer
736
+ store %Stack null, ptr %stack_pointer
737
+ call void @eraseStack(%Stack %stack)
738
+ ret void
739
+ }
645
740
 
646
- %stackPointer = load %StackPointer, ptr %stackStackPointer
647
- %region = load %Region, ptr %stackRegion
648
- %rest = load %Stack, ptr %stackRest
741
+ define void @eraseStack(%Stack %stack) alwaysinline {
742
+ %stackPointer_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 0
743
+ %region_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 2
744
+ %prompt_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 3
745
+ %dirtyBit_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
746
+ %rest_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 5
747
+
748
+ %stackPointer = load %StackPointer, ptr %stackPointer_pointer
749
+ %region = load %Region, ptr %region_pointer
750
+ %prompt = load %Stack, ptr %prompt_pointer
751
+ %dirtyBit = load i1, ptr %dirtyBit_pointer
752
+ %rest = load %Stack, ptr %rest_pointer
649
753
 
650
754
  call void @free(%Stack %stack)
651
755
  call void @eraseFrames(%StackPointer %stackPointer)
652
756
  call void @eraseRegion(%Region %region)
757
+ call void @erasePrompt(%Prompt %prompt, i1 %dirtyBit)
653
758
 
654
759
  %isNull = icmp eq %Stack %rest, null
655
760
  br i1 %isNull, label %done, label %next
@@ -696,10 +801,13 @@ define private void @topLevelEraser(%Environment %environment) {
696
801
  ret void
697
802
  }
698
803
 
804
+ @global = private global { i64, %Stack } { i64 0, %Stack null }
805
+
699
806
  define private %Stack @withEmptyStack() {
700
- ; TODO all stacks share the same source of fresh prompts
701
- %prompt = call %Prompt @freshPrompt()
702
- %stack = call %Stack @newStack(%Prompt %prompt)
807
+ %stack = call %Stack @reset(%Stack null)
808
+
809
+ %globalStack = getelementptr %PromptValue, %Prompt @global, i64 0, i32 1
810
+ store %Stack %stack, ptr %globalStack
703
811
 
704
812
  %stackStackPointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 0
705
813
  %stackPointer = load %StackPointer, ptr %stackStackPointer
@@ -4,10 +4,11 @@
4
4
 
5
5
  typedef int64_t Int;
6
6
  typedef double Double;
7
+ typedef uint8_t Byte;
7
8
 
8
9
  struct Header {
9
- uint64_t rc;
10
- void (*eraser)(void *);
10
+ uint64_t rc;
11
+ void (*eraser)(void *);
11
12
  };
12
13
 
13
14
  struct Pos {