@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.
- 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.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_primitives.ss +105 -0
- package/libraries/chez/common/immutable/cslist.effekt +37 -0
- package/libraries/chez/common/mutable/dict.effekt +28 -0
- package/libraries/chez/common/text/pregexp.scm +772 -0
- package/libraries/chez/common/text/regex.effekt +31 -0
- package/libraries/chez/lift/effekt.ss +118 -0
- package/libraries/chez/monadic/effekt.ss +84 -0
- package/libraries/chez/monadic/seq0.ss +76 -0
- package/libraries/common/args.effekt +95 -0
- package/libraries/common/array.effekt +225 -0
- package/libraries/common/bench.effekt +60 -0
- package/libraries/common/buffer.effekt +123 -0
- package/libraries/common/bytes.effekt +125 -0
- package/libraries/common/dequeue.effekt +92 -0
- package/libraries/common/effekt.effekt +764 -0
- package/libraries/common/exception.effekt +122 -0
- package/libraries/common/io/console.effekt +66 -0
- package/libraries/common/io/error.effekt +365 -0
- package/libraries/common/io/files.effekt +282 -0
- package/libraries/common/io/network.effekt +105 -0
- package/libraries/common/io/time.effekt +15 -0
- package/libraries/common/io.effekt +158 -0
- package/libraries/common/list.effekt +687 -0
- package/libraries/common/option.effekt +72 -0
- package/libraries/common/process.effekt +10 -0
- package/libraries/common/queue.effekt +140 -0
- package/libraries/common/ref.effekt +63 -0
- package/libraries/common/result.effekt +45 -0
- package/libraries/common/seq.effekt +914 -0
- package/libraries/common/string.effekt +395 -0
- package/libraries/common/test.effekt +98 -0
- package/libraries/js/effekt_builtins.js +57 -0
- package/libraries/js/effekt_runtime.js +385 -0
- package/libraries/js/io.js +143 -0
- package/libraries/js/mutable/map.effekt +31 -0
- package/libraries/js/text/regex.effekt +33 -0
- package/libraries/js/unsafe/cont.effekt +11 -0
- package/libraries/js/web/dom.effekt +45 -0
- package/libraries/llvm/array.c +53 -0
- package/libraries/llvm/buffer.c +286 -0
- package/libraries/llvm/forward-declare-c.ll +43 -0
- package/libraries/llvm/hole.c +11 -0
- package/libraries/llvm/io.c +566 -0
- package/libraries/llvm/io.ll +19 -0
- package/libraries/llvm/main.c +41 -0
- package/libraries/llvm/ref.c +45 -0
- package/libraries/llvm/rts.ll +761 -0
- package/libraries/llvm/sanity.c +16 -0
- package/libraries/llvm/types.c +43 -0
- package/libraries/ml/effekt.sml +65 -0
- package/libraries/ml/internal/mllist.effekt +9 -0
- package/libraries/ml/internal/mloption.effekt +18 -0
- package/libraries/ml/random.effekt +85 -0
- package/libraries/ml/text/regex.effekt +102 -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 +1239 -0
- package/licenses/the apache software license, version 2.0 - license-2.0.txt +202 -0
- package/licenses/the bsd license - bsd-license.html +1237 -0
- package/licenses/the mit license - mit.html +1239 -0
- 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
|
+
}
|