-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathGlulx Runtime Instrumentation Framework.i7x
2989 lines (2307 loc) · 157 KB
/
Glulx Runtime Instrumentation Framework.i7x
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Version 1 of Glulx Runtime Instrumentation Framework (for Glulx only) by Brady Garvin begins here.
"A framework for safely transforming a story's Glulx bytecode at runtime."
Include Compiler Version Checks by Brady Garvin.
Include Runtime Checks by Brady Garvin.
Include Low-Level Operations by Brady Garvin.
Include Object Pools by Brady Garvin.
Include Low-Level Text by Brady Garvin.
Include Low-Level Linked Lists by Brady Garvin.
Include Low-Level Hash Tables by Brady Garvin.
Include Human-Friendly Function Names by Brady Garvin.
Include I6 Routine Names by Brady Garvin.
Use authorial modesty.
Book "Copyright and License"
[Copyright 2013 Brady J. Garvin]
[This extension is released under the Creative Commons Attribution 3.0 Unported License (CC BY 3.0) so that it can qualify as a public Inform extension. See the LICENSE file included in the release for further details.]
Book "Extension Information"
[I'm not much for acronyms, but at the moment none of the IDEs complete I7 identifiers, and people get tired of typing long names. Therefore, I will make one exception throughout the extension, beginning with this say phrase.]
To say GRIF:
say "Glulx Runtime Instrumentation Framework".
[For each of the kinds defined by Glulx Runtime Instrumentation Framework you will see a sentence like
A operation code record is an invalid operation code record.
This bewildering statement actually sets up operation code records as a qualitative value with default value the operation code record at address one, which, as we say, is invalid. (We could have gone with a quantitative kind for default zero, but then we would open up the possibility for arithmetic on the pointers.) I wish it weren't necessary, but at least in this build Inform doesn't let us provide a default value any other way, and, moreover, we need a default value or else only I6 substitutions are allowed to decide on operation code records.]
Chapter "Use Options" - unindexed
Use hot-swappable instrumentation translates as (- Constant GRIF_HOT_SWAP; -)
Use a GRIF substitution hash table size of at least 311 translates as (- Constant GRIF_SUBSTITUTION_HASH_SIZE={N}; -).
Use a GRIF operation code hash table size of at least 1123 translates as (- Constant GRIF_OPERATION_HASH_SIZE={N}; -).
Use a GRIF instruction vertex hash table size of at least 1123 translates as (- Constant GRIF_VERTEX_HASH_SIZE={N}; -).
Use a GRIF chunk translation hash table size of at least 3121 translates as (- Constant GRIF_CHUNK_HASH_SIZE={N}; -).
Use a GRIF hot-swap hash table size of at least 11213 translates as (- Constant GRIF_HOT_SWAP_HASH_SIZE={N}; -).
Use a GRIF disassembly label hash table size of at least 23 translates as (- Constant GRIF_DISASSEMBLY_LABEL_HASH_SIZE={N}; -).
Use a GRIF instruction vertex preallocation of at least 8192 translates as (- Constant GRIF_INSTRUCTION_VERTEX_PREALLOC={N}; -).
To decide what number is the GRIF substitution hash table size: (- GRIF_SUBSTITUTION_HASH_SIZE -).
To decide what number is the GRIF operation code hash table size: (- GRIF_OPERATION_HASH_SIZE -).
To decide what number is the GRIF instruction vertex hash table size: (- GRIF_VERTEX_HASH_SIZE -).
To decide what number is the GRIF chunk translation hash table size: (- GRIF_CHUNK_HASH_SIZE -).
To decide what number is the GRIF hot-swap hash table size: (- GRIF_HOT_SWAP_HASH_SIZE -).
To decide what number is the GRIF disassembly label hash table size: (- GRIF_DISASSEMBLY_LABEL_HASH_SIZE -).
To decide what number is the GRIF instruction vertex preallocation: (- GRIF_INSTRUCTION_VERTEX_PREALLOC -).
Chapter "Rulebooks"
The GRIF pre-hijacking rules are [rulebook is] a rulebook.
The GRIF setup rules are [rulebook is] a rulebook.
The GRIF anticipation rules are [rulebook is] a rulebook.
The GRIF shielding rules are [rulebook is] a rulebook.
The GRIF post-hijacking rules are [rulebook is] a rulebook.
The GRIF instrumented post-hijacking rules are [rulebook is] a rulebook.
The GRIF emendation rules are [rulebook is] a rulebook.
The GRIF instrumentation rules are [rulebook is] a rulebook.
The GRIF instrumentation adjustment rules are [rulebook is] a rulebook.
The GRIF internal instrumentation rules are [rulebook is] a rulebook.
The GRIF capture rules are [rulebook is] a rulebook.
Book "Runtime Checks"
Chapter "Environment Checks"
An environment check rule (this is the check for a modern Glulx to support GRIF rule):
always check that the encoded Glulx version is at least 196864 or else say "[low-level runtime failure in]the [GRIF][with explanation]This story uses the [GRIF] (GRIF), which in turn depends on features added to the Glulx specification in version 3.1.0. But this interpreter implements an older version of Glulx, meaning that GRIF cannot safely run.[terminating the story]".
An environment check rule (this is the check for dynamic memory allocation to support GRIF rule):
always check that memory allocation is supported or else say "[low-level runtime failure in]the [GRIF][with explanation]This story uses the [GRIF] (GRIF), which in turn depends on dynamic memory allocation. But this interpreter doesn't allow dynamic memory allocation, meaning that GRIF cannot safely run.[terminating the story]".
To decide what text is the last compiler version GRIF has been tested with:
decide on "6G60".
An environment check rule (this is the check for a tested Inform version to support GRIF rule):
always check that the current compiler version is at least the compiler version the last compiler version GRIF has been tested with or else say "[low-level runtime failure in]the [GRIF][with explanation]The story was compiled with Inform 7 version [the formatted current compiler version], but the [GRIF] has not been tested on versions of Inform before [the last compiler version GRIF has been tested with]. (If you understand the risks, you can suppress this message by writing[line break][line break][fixed letter spacing] The check for a tested Inform version to support GRIF rule is not listed in the environment check rulebook.[variable letter spacing][warning type][line break][line break]in the source text.)[terminating the story]".
Chapter "Failure Messages" - unindexed
To fail at finding the hijack main rule in the startup rulebook (this is failing at finding the hijack main rule in the startup rulebook):
say "[low-level runtime failure in]the [GRIF][with explanation]I tried to run the hijack main rule, but it wasn't called from within the startup rulebook, which is where it ought to be.[terminating the story]".
To fail at sign extending the lower (W - a number) bytes of (I - a number):
say "[low-level runtime failure in]the [GRIF][with explanation]I tried to treat the lower [W in words] bytes of [I in hexadecimal] as something to sign extend, but I can only extend from zero, one, two, or four bytes.[terminating the story]".
To fail at reading (W - a number) bytes at address (A - a number):
say "[low-level runtime failure in]the [GRIF][with explanation]I tried to read the [W in words] bytes at address [A in hexadecimal] as a unit, but I can only read zero-, one-, two-, or four-byte segments at a time.[terminating the story]".
To fail at recognizing the operation code (C - a number):
say "[low-level runtime failure in]the [GRIF][with explanation][if the human-friendly function name hash table is not the invalid permanent hash table]While processing [the human-friendly name for the function at address the address of the chunk being instrumented] (at address [the address of the chunk being instrumented]/[the address of the chunk being instrumented in hexadecimal]), [end if]I encountered operation code [C in hexadecimal] ([C converted to a number] in decimal), which I know nothing about. Perhaps the Table of Glulx Operation Codes is incomplete or corrupted? Or maybe there is a mistake in the pointer arithmetic?[terminating the story]".
To fail at recognizing the function type (B - a number) for the function at address (A - a number):
say "[low-level runtime failure in]the [GRIF][with explanation]I was expecting to find a function at address [A in hexadecimal], but the first byte was [B in hexadecimal], which, so far as I know, is not a valid starting byte for a function. (Usually this means that the story tried to call a nonfunction as if it were a function, in which case it's about to crash.)[terminating the story]".
To fail at instrumenting nothing with (A - an instruction vertex):
say "[low-level runtime failure in]the [GRIF][with explanation]I was asked to insert an instruction vertex ([the I6-like assembly of A]) at a time when nothing was being instrumented.[terminating the story]".
To fail at reusing (A - an instruction vertex):
say "[low-level runtime failure in]the [GRIF][with explanation][if the human-friendly function name hash table is not the invalid permanent hash table]While processing [the human-friendly name for the function at address the address of the chunk being instrumented], [end if]I was asked to insert an instruction vertex ([the I6-like assembly of A]) twice, even though vertices can have only one location.[terminating the story]".
To fail at inserting (B - an instruction vertex) after (A - an instruction vertex) with no fallthrough:
say "[low-level runtime failure in]the [GRIF][with explanation][if the human-friendly function name hash table is not the invalid permanent hash table]While processing [the human-friendly name for the function at address the address of the chunk being instrumented], [end if]I was asked to insert an instruction vertex ([the I6-like assembly of B]) after another vertex with no fallthrough ([the I6-like assembly of A]).[terminating the story]".
To fail at jumping vaguely from (A - an instruction vertex):
say "[low-level runtime failure in]the [GRIF][with explanation][if the human-friendly function name hash table is not the invalid permanent hash table]While processing [the human-friendly name for the function at address the address of the chunk being instrumented], [end if]I tried to compute a jump parameter for an instruction ([the I6-like assembly of A]) without first figuring out where I was going to place it.[terminating the story]".
To fail at emitting the unplaced (A - an instruction vertex):
say "[low-level runtime failure in]the [GRIF][with explanation][if the human-friendly function name hash table is not the invalid permanent hash table]While processing [the human-friendly name for the function at address the address of the chunk being instrumented], [end if]I tried to emit an instruction ([the I6-like assembly of A]) without first figuring out where I was going to place it.[terminating the story]".
To fail at self-instrumenting:
say "[low-level runtime failure in]the [GRIF][with explanation]I was asked to instrument the [GRIF] itself, but I lack the requisite cleverness; to try would be like attempting a self-administered lobotomy. Check that you aren't using the rules and phrases for instrumenting in the wrong context, either directly or by including instrumentation that injects them.[terminating the story]".
To fail at starting GRIF twice:
say "[low-level runtime failure in]the [GRIF][with explanation]I was asked to start the [GRIF] a second time, but it can only be started once.[terminating the story]".
To fail at guessing the routine kernel of (A - a number) mid-instrumentation:
say "[low-level runtime failure in]the [GRIF][with explanation]I was asked to ensure knowledge of any routine kernel of [the human-friendly name for the function at address A], but to do so I need access to the scratch space. It's currently occupied.[terminating the story]".
To fail at initializing the disassembly label hash table twice with no intervening teardown:
say "[low-level runtime failure in]the [GRIF][with explanation]I was asked to initialize the disassembly label hash table, but it was already initialized, and would need to be torn down before it could be initialized again.[terminating the story]".
To fail at tearing down the uninitialized disassembly label hash table:
say "[low-level runtime failure in]the [GRIF][with explanation]I was asked to tear down the disassembly label hash table, but it wasn't initialized, and so could not be torn down.[terminating the story]".
Book "Additional Low-Level Operations" - unindexed
Chapter "Sign Extension" - unindexed
To decide what number is the sign extension of (I - a number) from (W - a number) byte/bytes:
if W is:
-- 0:
decide on zero;
-- 1:
decide on I sign extended from a byte;
-- 2:
decide on I sign extended from a short;
-- 4:
decide on I;
fail at sign extending the lower W bytes of I.
Chapter "Reading Memory" - unindexed
To decide what number is the (W - a number) byte/bytes at address (A - a number):
if W is:
-- 0:
decide on zero;
-- 1:
decide on the byte at address A;
-- 2:
decide on the short at address A;
-- 4:
decide on the integer at address A;
fail at reading W bytes at address A.
Chapter "Addressing modes"
Addressing mode is a kind of value. The addressing modes are the invalid addressing mode, the zero-or-discard addressing mode, the constant addressing mode, the zero-based-dereference addressing mode, the stack addressing mode, the call-frame-local addressing mode, the ram-based-dereference addressing mode, the start-of-vertex addressing mode, and the near-end-of-vertex addressing mode. The specification of an addressing mode is "The Glulx addressing modes represent the various ways that a Glulx instruction can read or write values. They are documented in Section 1.5 of the Glulx VM specification, except for the start-of-vertex and near-end-of-vertex addressing modes. GRIF changes the start-of-vertex addressing mode to a constant by following two steps: 1. find the instruction vertex at the address given and 2. determine where its instruction is emitted. Near-end-of-vertex addressing mode is similar, and signifies a constant computed by those steps and also two more: 3. find the address at which a subsequent instruction could first appear, and 4. subtract two. In other words, near-end-of-vertex addressing mode means the base address for relative jumps from the indicated vertex."
Section "Addressing Mode Encodings and Sizes" - unindexed
Every addressing mode has a number called the nybble for the widest encoding.
The nybble for the widest encoding of the invalid addressing mode is 4.
The nybble for the widest encoding of the zero-or-discard addressing mode is 0.
The nybble for the widest encoding of the constant addressing mode is 3.
The nybble for the widest encoding of the zero-based-dereference addressing mode is 7.
The nybble for the widest encoding of the stack addressing mode is 8.
The nybble for the widest encoding of the call-frame-local addressing mode is 11.
The nybble for the widest encoding of the ram-based-dereference addressing mode is 15.
The nybble for the widest encoding of the start-of-vertex addressing mode is 3.
The nybble for the widest encoding of the near-end-of-vertex addressing mode is 3.
Include (-
Array GRIF_ADDRESSING_WIDTHS -->
0 1 2 4
0 1 2 4
0 1 2 4
0 1 2 4;
Array GRIF_ADDRESSING_MODES -->
(+ the zero-or-discard addressing mode +) ! 0
(+ the constant addressing mode +) ! 1
(+ the constant addressing mode +) ! 2
(+ the constant addressing mode +) ! 3
(+ the invalid addressing mode +) ! 4
(+ the zero-based-dereference addressing mode +) ! 5
(+ the zero-based-dereference addressing mode +) ! 6
(+ the zero-based-dereference addressing mode +) ! 7
(+ the stack addressing mode +) ! 8
(+ the call-frame-local addressing mode +) ! 9
(+ the call-frame-local addressing mode +) ! A
(+ the call-frame-local addressing mode +) ! B
(+ the invalid addressing mode +) ! C
(+ the ram-based-dereference addressing mode +) ! D
(+ the ram-based-dereference addressing mode +) ! E
(+ the ram-based-dereference addressing mode +); ! F
-).
To decide what addressing mode is the addressing mode corresponding to the nybble (N - a number): (- llo_getField(GRIF_ADDRESSING_MODES,{N}) -).
To decide what number is the size corresponding to the nybble (N - a number): (- llo_getField(GRIF_ADDRESSING_WIDTHS,{N}) -).
Chapter "Operation Codes"
Section "Operation Code Parameters" - unindexed
Include (-
Constant GRIF_MAX_PARAMETERS = 8;
-) after "Definitions.i6t".
To decide what number is the maximum number of parameters taken by any Glulx operation code: (- GRIF_MAX_PARAMETERS -).
Section "Influence on Control Flow"
Influence on control flow is a kind of value. The plural of influence on control flow is influences on control flow. The influences on control flow are ordinary control flow, jump without call, function call, string call, exception throw, exception catch, change of decoding table, and GLK call. The specification of an influence on control flow is "The influences on control flow describe how a Glulx operation can affect the instruction pointer. Most operations are marked with 'ordinary control flow' to indicate that they will fallthrough if their fallthrough flag is set, or else terminate the enclosing function (and perhaps the story as well). Other possibilities include a jump, a call, an exception throw, etc. In one unusual case an operation changes the decoding table before falling through, and the Glulx Runtime Instrumentation Framework treats that as a special case."
Section "The Table of Glulx Operation Codes"
Table of Glulx Operation Codes
I6 Assembly Name Operation Code Parameter Count Load Parameter Count Fallthrough Influence on Control Flow Relative Jump Addressing Jump Parameter Index
"nop" 0 0 0 true ordinary control flow false 0
"add" 16 3 2 true ordinary control flow false 0
"sub" 17 3 2 true ordinary control flow false 0
"mul" 18 3 2 true ordinary control flow false 0
"div" 19 3 2 true ordinary control flow false 0
"mod" 20 3 2 true ordinary control flow false 0
"neg" 21 2 1 true ordinary control flow false 0
"bitand" 24 3 2 true ordinary control flow false 0
"bitor" 25 3 2 true ordinary control flow false 0
"bitxor" 26 3 2 true ordinary control flow false 0
"bitnot" 27 2 1 true ordinary control flow false 0
"shiftl" 28 3 2 true ordinary control flow false 0
"sshiftr" 29 3 2 true ordinary control flow false 0
"ushiftr" 30 3 2 true ordinary control flow false 0
"jump" 32 1 1 false jump without call true 0
"jz" 34 2 2 true jump without call true 1
"jnz" 35 2 2 true jump without call true 1
"jeq" 36 3 3 true jump without call true 2
"jne" 37 3 3 true jump without call true 2
"jlt" 38 3 3 true jump without call true 2
"jge" 39 3 3 true jump without call true 2
"jgt" 40 3 3 true jump without call true 2
"jle" 41 3 3 true jump without call true 2
"jltu" 42 3 3 true jump without call true 2
"jgeu" 43 3 3 true jump without call true 2
"jgtu" 44 3 3 true jump without call true 2
"jleu" 45 3 3 true jump without call true 2
"call" 48 3 2 true function call false 0
"return" 49 1 1 false ordinary control flow false 0
"catch" 50 2 1 true exception catch true 1
"throw" 51 2 2 false exception throw false 0
"tailcall" 52 2 2 false function call false 0
"copy" 64 2 1 true ordinary control flow false 0
"copys" 65 2 1 true ordinary control flow false 0
"copyb" 66 2 1 true ordinary control flow false 0
"sexs" 68 2 1 true ordinary control flow false 0
"sexb" 69 2 1 true ordinary control flow false 0
"aload" 72 3 2 true ordinary control flow false 0
"aloads" 73 3 2 true ordinary control flow false 0
"aloadb" 74 3 2 true ordinary control flow false 0
"aloadbit" 75 3 2 true ordinary control flow false 0
"astore" 76 3 3 true ordinary control flow false 0
"astores" 77 3 3 true ordinary control flow false 0
"astoreb" 78 3 3 true ordinary control flow false 0
"astorebit" 79 3 3 true ordinary control flow false 0
"stkcount" 80 1 0 true ordinary control flow false 0
"stkpeek" 81 2 1 true ordinary control flow false 0
"stkswap" 82 0 0 true ordinary control flow false 0
"stkroll" 83 2 2 true ordinary control flow false 0
"stkcopy" 84 1 1 true ordinary control flow false 0
"streamchar" 112 1 1 true ordinary control flow false 0
"streamnum" 113 1 1 true ordinary control flow false 0
"streamstr" 114 1 1 true string call false 0
"streamunichar" 115 1 1 true ordinary control flow false 0
"gestalt" 256 3 2 true ordinary control flow false 0
"debugtrap" 257 1 1 true ordinary control flow false 0
"getmemsize" 258 1 0 true ordinary control flow false 0
"setmemsize" 259 2 1 true ordinary control flow false 0
"jumpabs" 260 1 1 false jump without call false 0
"random" 272 2 1 true ordinary control flow false 0
"setrandom" 273 1 1 true ordinary control flow false 0
"quit" 288 0 0 false ordinary control flow false 0
"verify" 289 1 0 true ordinary control flow false 0
"restart" 290 0 0 false ordinary control flow false 0
"save" 291 2 1 true ordinary control flow false 0
"restore" 292 2 1 false ordinary control flow false 0
"saveundo" 293 1 0 true ordinary control flow false 0
"restoreundo" 294 1 0 true ordinary control flow false 0
"protect" 295 2 2 true ordinary control flow false 0
"glk" 304 3 2 true GLK call false 0
"getstringtbl" 320 1 0 true ordinary control flow false 0
"setstringtbl" 321 1 1 true change of decoding table false 0
"getiosys" 328 2 0 true ordinary control flow false 0
"setiosys" 329 2 2 true ordinary control flow false 0
"linearsearch" 336 8 7 true ordinary control flow false 0
"binarysearch" 337 8 7 true ordinary control flow false 0
"linkedsearch" 338 7 6 true ordinary control flow false 0
"callf" 352 2 1 true function call false 0
"callfi" 353 3 2 true function call false 0
"callfii" 354 4 3 true function call false 0
"callfiii" 355 5 4 true function call false 0
"mzero" 368 2 2 true ordinary control flow false 0
"mcopy" 369 3 3 true ordinary control flow false 0
"malloc" 376 2 1 true ordinary control flow false 0
"mfree" 377 1 1 true ordinary control flow false 0
"accelfunc" 384 2 2 true ordinary control flow false 0
"accelparam" 385 2 2 true ordinary control flow false 0
"numtof" 400 2 1 true ordinary control flow false 0
"ftonumz" 401 2 1 true ordinary control flow false 0
"ftonumn" 402 2 1 true ordinary control flow false 0
"ceil" 408 2 1 true ordinary control flow false 0
"floor" 409 2 1 true ordinary control flow false 0
"fadd" 416 3 2 true ordinary control flow false 0
"fsub" 417 3 2 true ordinary control flow false 0
"fmul" 418 3 2 true ordinary control flow false 0
"fdiv" 419 3 2 true ordinary control flow false 0
"fmod" 420 4 3 true ordinary control flow false 0
"sqrt" 424 2 1 true ordinary control flow false 0
"exp" 425 2 1 true ordinary control flow false 0
"log" 426 2 1 true ordinary control flow false 0
"pow" 427 3 2 true ordinary control flow false 0
"sin" 432 2 1 true ordinary control flow false 0
"cos" 433 2 1 true ordinary control flow false 0
"tan" 434 2 1 true ordinary control flow false 0
"asin" 435 2 1 true ordinary control flow false 0
"acos" 436 2 1 true ordinary control flow false 0
"atan" 437 2 1 true ordinary control flow false 0
"atan2" 438 3 2 true ordinary control flow false 0
"jfeq" 448 4 4 true jump without call true 3
"jfne" 449 4 4 true jump without call true 3
"jflt" 450 3 3 true jump without call true 2
"jfle" 451 3 3 true jump without call true 2
"jfgt" 452 3 3 true jump without call true 2
"jfge" 453 3 3 true jump without call true 2
"jisnan" 456 2 2 true jump without call true 1
"jisinf" 457 2 2 true jump without call true 1
"git" 31040 1 1 true ordinary control flow false 0
[To make writing literal operation codes easier, we define the following. But we don't want them to take up any more space than necessary, so they are all inlined I6 constants.]
To decide what number is op-nop: (- 0 -).
To decide what number is op-add: (- 16 -).
To decide what number is op-sub: (- 17 -).
To decide what number is op-mul: (- 18 -).
To decide what number is op-div: (- 19 -).
To decide what number is op-mod: (- 20 -).
To decide what number is op-neg: (- 21 -).
To decide what number is op-bitand: (- 24 -).
To decide what number is op-bitor: (- 25 -).
To decide what number is op-bitxor: (- 26 -).
To decide what number is op-bitnot: (- 27 -).
To decide what number is op-shiftl: (- 28 -).
To decide what number is op-sshiftr: (- 29 -).
To decide what number is op-ushiftr: (- 30 -).
To decide what number is op-jump: (- 32 -).
To decide what number is op-jz: (- 34 -).
To decide what number is op-jnz: (- 35 -).
To decide what number is op-jeq: (- 36 -).
To decide what number is op-jne: (- 37 -).
To decide what number is op-jlt: (- 38 -).
To decide what number is op-jge: (- 39 -).
To decide what number is op-jgt: (- 40 -).
To decide what number is op-jle: (- 41 -).
To decide what number is op-jltu: (- 42 -).
To decide what number is op-jgeu: (- 43 -).
To decide what number is op-jgtu: (- 44 -).
To decide what number is op-jleu: (- 45 -).
To decide what number is op-call: (- 48 -).
To decide what number is op-return: (- 49 -).
To decide what number is op-catch: (- 50 -).
To decide what number is op-throw: (- 51 -).
To decide what number is op-tailcall: (- 52 -).
To decide what number is op-copy: (- 64 -).
To decide what number is op-copys: (- 65 -).
To decide what number is op-copyb: (- 66 -).
To decide what number is op-sexs: (- 68 -).
To decide what number is op-sexb: (- 69 -).
To decide what number is op-aload: (- 72 -).
To decide what number is op-aloads: (- 73 -).
To decide what number is op-aloadb: (- 74 -).
To decide what number is op-aloadbit: (- 75 -).
To decide what number is op-astore: (- 76 -).
To decide what number is op-astores: (- 77 -).
To decide what number is op-astoreb: (- 78 -).
To decide what number is op-astorebit: (- 79 -).
To decide what number is op-stkcount: (- 80 -).
To decide what number is op-stkpeek: (- 81 -).
To decide what number is op-stkswap: (- 82 -).
To decide what number is op-stkroll: (- 83 -).
To decide what number is op-stkcopy: (- 84 -).
To decide what number is op-streamchar: (- 112 -).
To decide what number is op-streamnum: (- 113 -).
To decide what number is op-streamstr: (- 114 -).
To decide what number is op-streamunichar: (- 115 -).
To decide what number is op-gestalt: (- 256 -).
To decide what number is op-debugtrap: (- 257 -).
To decide what number is op-getmemsize: (- 258 -).
To decide what number is op-setmemsize: (- 259 -).
To decide what number is op-jumpabs: (- 260 -).
To decide what number is op-random: (- 272 -).
To decide what number is op-setrandom: (- 273 -).
To decide what number is op-quit: (- 288 -).
To decide what number is op-verify: (- 289 -).
To decide what number is op-restart: (- 290 -).
To decide what number is op-save: (- 291 -).
To decide what number is op-restore: (- 292 -).
To decide what number is op-saveundo: (- 293 -).
To decide what number is op-restoreundo: (- 294 -).
To decide what number is op-protect: (- 295 -).
To decide what number is op-glk: (- 304 -).
To decide what number is op-getstringtbl: (- 320 -).
To decide what number is op-setstringtbl: (- 321 -).
To decide what number is op-getiosys: (- 328 -).
To decide what number is op-setiosys: (- 329 -).
To decide what number is op-linearsearch: (- 336 -).
To decide what number is op-binarysearch: (- 337 -).
To decide what number is op-linkedsearch: (- 338 -).
To decide what number is op-callf: (- 352 -).
To decide what number is op-callfi: (- 353 -).
To decide what number is op-callfii: (- 354 -).
To decide what number is op-callfiii: (- 355 -).
To decide what number is op-mzero: (- 368 -).
To decide what number is op-mcopy: (- 369 -).
To decide what number is op-malloc: (- 376 -).
To decide what number is op-mfree: (- 377 -).
To decide what number is op-accelfunc: (- 384 -).
To decide what number is op-accelparam: (- 385 -).
To decide what number is op-numtof: (- 400 -).
To decide what number is op-ftonumz: (- 401 -).
To decide what number is op-ftonumn: (- 402 -).
To decide what number is op-ceil: (- 408 -).
To decide what number is op-floor: (- 409 -).
To decide what number is op-fadd: (- 416 -).
To decide what number is op-fsub: (- 417 -).
To decide what number is op-fmul: (- 418 -).
To decide what number is op-fdiv: (- 419 -).
To decide what number is op-fmod: (- 420 -).
To decide what number is op-sqrt: (- 424 -).
To decide what number is op-exp: (- 425 -).
To decide what number is op-log: (- 426 -).
To decide what number is op-pow: (- 427 -).
To decide what number is op-sin: (- 432 -).
To decide what number is op-cos: (- 433 -).
To decide what number is op-tan: (- 434 -).
To decide what number is op-asin: (- 435 -).
To decide what number is op-acos: (- 436 -).
To decide what number is op-atan: (- 437 -).
To decide what number is op-atan2: (- 438 -).
To decide what number is op-jfeq: (- 448 -).
To decide what number is op-jfne: (- 449 -).
To decide what number is op-jflt: (- 450 -).
To decide what number is op-jfle: (- 451 -).
To decide what number is op-jfgt: (- 452 -).
To decide what number is op-jfge: (- 453 -).
To decide what number is op-jisnan: (- 456 -).
To decide what number is op-jisinf: (- 457 -).
Chapter "Operation Code Records" - unindexed
Section "The Operation Code Record Kind" - unindexed
A operation code record is a kind of value.
A operation code record is an invalid operation code record. [See the note in the book "Extension Information."]
The specification of an operation code record is "Operation code records represent rows from the Table of Glulx Operation Codes in a form more convenient for the Glulx Runtime Instrumentation Framework. They are only used internally."
Section "The Operation Code Record Structure" - unindexed
[Layout:
4 bytes for the operation code
4 bytes for the parameter limit (the parameter count less one)
4 bytes for the parameter mode byte count (half the parameter count, rounded up)
4 bytes for the fallthrough flag
4 bytes for the influence on control flow
4 bytes for the relative jump addressing flag
4 bytes for the jump parameter index
4 bytes for the I6 assembly name
4 bytes for the load parameter limit entry]
[The first 28 bytes (up through the jump parameter index) must match the layout of instruction vertices.]
To decide what number is the size in memory of an operation code record: (- 36 -).
Section "Operation Code Record Construction and Destruction" - unindexed
To decide what operation code record is a new operation code record:
decide on a permanent memory allocation of the size in memory of an operation code record bytes converted to an operation code record.
[Operation code records are never deleted.]
Section "Operation Code Record Accessors and Mutators" - unindexed
To decide what number is the operation code of (A - an operation code record): (- llo_getInt({A}) -).
To write the operation code (X - a number) to (A - an operation code record): (- llo_setInt({A},{X}); -).
To decide what number is the parameter limit of (A - an operation code record): (- llo_getField({A},1) -).
To write the parameter limit (X - a number) to (A - an operation code record): (- llo_setField({A},1,{X}); -).
To decide what number is the parameter mode byte count of (A - an operation code record): (- llo_getField({A},2) -).
To write the parameter mode byte count (X - a number) to (A - an operation code record): (- llo_setField({A},2,{X}); -).
To decide whether the fallthrough flag is set in (A - an operation code record): (- llo_getField({A},3) -).
To write the fallthrough flag (X - a truth state) to (A - an operation code record): (- llo_setField({A},3,{X}); -).
To decide what influence on control flow is the influence on control flow of (A - an operation code record): (- llo_getField({A},4) -).
To write the influence on control flow (X - an influence on control flow) to (A - an operation code record): (- llo_setField({A},4,{X}); -).
To decide whether the relative jump addressing flag is set in (A - an operation code record): (- llo_getField({A},5) -).
To write the relative jump addressing flag (X - a truth state) to (A - an operation code record): (- llo_setField({A},5,{X}); -).
To decide what number is the jump parameter index of (A - an operation code record): (- llo_getField({A},6) -).
To write the jump parameter index (X - a number) to (A - an operation code record): (- llo_setField({A},6,{X}); -).
To decide what text is the I6 assembly name of (A - an operation code record): (- llo_getField({A},7) -).
To write the I6 assembly name (X - some text) to (A - an operation code record): (- llo_setField({A},7,{X}); -).
To decide what number is the load parameter limit of (A - an operation code record): (- llo_getField({A},8) -).
To write the load parameter limit (X - a number) to (A - an operation code record): (- llo_setField({A},8,{X}); -).
To copy the shared fields of (A - an operation code record) to (B - an instruction vertex): (- llo_copy(28,{A},{B}); -).
Chapter "Operation Code Hash Table" - unindexed
The operation code hash table is a permanent hash table that varies.
A GRIF setup rule (this is the allocate a permanent hash table for the Glulx operation codes rule):
now the operation code hash table is a new permanent hash table with the GRIF operation code hash table size buckets;
repeat through the Table of Glulx Operation Codes:
let the record be a new operation code record;
write the I6 assembly name I6 assembly name entry to the record;
write the operation code operation code entry to the record;
[The parameter limit is the parameter count minus one.]
let the transformed parameter count be the parameter count entry minus one;
write the parameter limit transformed parameter count to the record;
[The parameter mode byte count is half the parameter count, rounding up.]
now the transformed parameter count is the transformed parameter count arithmetically shifted one bit right;
increment the transformed parameter count;
write the parameter mode byte count transformed parameter count to the record;
write the load parameter limit load parameter count entry minus one to the record;
write the fallthrough flag fallthrough entry to the record;
write the influence on control flow influence on control flow entry to the record;
write the relative jump addressing flag relative jump addressing entry to the record;
write the jump parameter index jump parameter index entry to the record;
insert the key the operation code entry and the value the record into the operation code hash table.
To decide what operation code record is the record for the operation code (C - a number):
let the permanent linked list vertex be the first match for the key C in the operation code hash table;
always check that the permanent linked list vertex is not null or else fail at recognizing the operation code C;
decide on the operation code record value of the permanent linked list vertex.
Book "Inform Information" - unindexed
Chapter "Routine Shell Identification" - unindexed
Section "Routine Shell Guesses" - unindexed
The kernel guess hash table is a permanent hash table that varies.
A GRIF setup rule (this is the allocate a permanent hash table for tracking kernel guesses rule):
now the kernel guess hash table is a new permanent hash table with the GRIF chunk translation hash table size buckets;
Section "Recognizing Routine Shell Components" - unindexed
To decide what number is blockv_stack: (- blockv_stack -).
To decide whether (A - an instruction vertex) couldn't be a pre-return aload in a routine shell:
if A is null:
decide yes;
[This test is most likely to reject, so it goes first (apart from the nonnullness test).]
if parameter zero of A is not blockv_stack:
decide yes;
if the operation code of A is not op-aload:
decide yes;
if the addressing mode of parameter zero of A is not the constant addressing mode:
decide yes;
if the addressing mode of parameter one of A is not the stack addressing mode:
decide yes;
if the addressing mode of parameter one of A is not the stack addressing mode:
decide yes;
decide no.
Section "The Emendation Rule for Routine Shell Identification"
A GRIF emendation rule (this is the detect routine shells rule):
if the kernel guess hash table contains the key the address of the chunk being instrumented:
stop;
insert the key the address of the chunk being instrumented into the kernel guess hash table;
repeat with the instruction vertex running through occurrences of the operation code op-return in the scratch space:
if the addressing mode of parameter zero of the instruction vertex is not the stack addressing mode or the previous link of the instruction vertex couldn't be a pre-return aload in a routine shell:
stop;
let the kernel address be zero;
repeat with the instruction vertex running through occurrences of function call in the scratch space:
if the addressing mode of parameter zero of the instruction vertex is not the constant addressing mode:
stop;
let the callee address be parameter zero of the instruction vertex;
if the callee address is not the address of I6_RT__Err and the callee address is not the address of I6_BlkValueCreate and the callee address is not the address of I6_BlkFree:
if the kernel address is not zero:
stop;
now the kernel address is the callee address;
if the kernel address is not zero:
associate the routine shell at address address of the chunk being instrumented with the routine kernel at address kernel address.
Section "Forcing Routine Shell Identification"
To guess the routine kernel for (A - a sayable value):
let the function address be the function address of A;
unless the kernel guess hash table contains the key the function address:
always check that the mutable address of the chunk being instrumented is zero or else fail at guessing the routine kernel of the function address mid-instrumentation;
parse the function at address the function address;
now the mutable address of the chunk being instrumented is the function address;
call the function at address the detect routine shells rule converted to a number;
now the mutable address of the chunk being instrumented is zero.
Book "Directed Graph Representation of Instruction Chunks"
Chapter "Instruction Vertices"
Section "The Instruction Vertex Kind"
An instruction vertex is a kind of value. The plural of instruction vertex is instruction vertices.
An instruction vertex is an invalid instruction vertex. [See the note in the book "Extension Information."]
The specification of an instruction vertex is "Instruction vertices represent a single Glulx instruction during the Glulx Runtime Instrumentation Framework's rewrite process. Besides gathering all of the information about an instruction into one data structure, instruction vertices also allow us to rearrange code quickly, and with the complications from jumps handled automatically."
Section "Instruction Vertex Constants"
To decide what instruction vertex is a null instruction vertex: (- 0 -).
Section "Instruction Vertex Adjectives"
Definition: an instruction vertex is null if it is a null instruction vertex.
Section "The Instruction Vertex Structure" - unindexed
[Layout:
4 bytes for the operation code
4 bytes for the parameter limit (the parameter count less one)
4 bytes for the parameter mode byte count (half the parameter count, rounded up)
4 bytes for the fallthrough flag
4 bytes for the influence on control flow
4 bytes for the relative jump addressing flag
4 bytes for the jump parameter index
4 bytes for the source address
4 bytes for the source end address
4 bytes for the destination offset
4 bytes for the destination end offset
4 bytes for the previous link
4 bytes for the next link
4 bytes for the sequence-ending instruction vertex address
4 bytes for the jump predecessor linked list
4 bytes for the jump link
8 bytes per parameter (out to the maximum number of parameters, usually eight): 4 for the addressing mode and 4 for the value
4 bytes for the shielded flag]
[The first 28 bytes (up through the jump parameter index) must match the layout of operation code records.]
[A new instruction vertex is normally filled with gibberish bits, except that none of the phrases that want to create new vertices will ever want the jump predecessor linked list address to be uninitialized or the shielded flag to be true; we guarantee that the former is null and the latter false.]
[Instruction vertices manage the lifetime of their jump predecessor linked lists; the linked list vertices are freed when the instruction vertex is deleted.]
[Parameters are numbered from zero.]
To decide what number is the size in memory of an instruction vertex:
let the space for parameters be eight times the maximum number of parameters taken by any Glulx operation code;
decide on 68 plus the space for parameters.
Section "Instruction Vertex Construction" - unindexed
The instruction vertex batch object pool is a batch object pool that varies.
A GRIF setup rule (this is the allocate a batch object pool for instruction vertices rule):
now the instruction vertex batch object pool is a new permanent batch object pool with the GRIF instruction vertex preallocation objects of size the size in memory of an instruction vertex bytes.
[Reminder: we guarantee that the jump predecessor linked list address is null, and that the shielded flag is reset, but everything else could be gibberish.]
To decide what instruction vertex is a new instruction vertex:
let the result be a memory allocation from the instruction vertex batch object pool converted to an instruction vertex;
write the jump predecessor linked list an empty linked list to the result;
reset the shielded flag in the result;
decide on the result.
To decide what instruction vertex is a new detached instruction vertex:
let the result be a memory allocation of the size in memory of an instruction vertex bytes converted to an instruction vertex;
write the jump predecessor linked list an empty linked list to the result;
reset the shielded flag in the result;
decide on the result.
Section "Instruction Vertex Destruction"
[We are not careful to fix up the pointers that other instruction vertices have to the moribund vertex, because vertices should only be deleted when we toss the whole scratch space out the window.]
To delete (A - an instruction vertex):
delete the jump predecessor linked list of A;
free the memory allocation at address (A converted to a number) to the instruction vertex batch object pool if it is external.
Section "Private Instruction Vertex Accessors and Mutators" - unindexed
To write the source address (X - a number) to (A - an instruction vertex): (- llo_setField({A},7,{X}); -).
To write the source end address (X - a number) to (A - an instruction vertex): (- llo_setField({A},8,{X}); -).
To write the destination offset (X - a number) to (A - an instruction vertex): (- llo_setField({A},9,{X}); -).
To write the destination end offset (X - a number) to (A - an instruction vertex): (- llo_setField({A},10,{X}); -).
To write the previous link (X - an instruction vertex) to (A - an instruction vertex): (- llo_setField({A},11,{X}); -).
To write the next link (X - an instruction vertex) to (A - an instruction vertex): (- llo_setField({A},12,{X}); -).
To decide what instruction vertex is the sequence-ending instruction vertex of (A - an instruction vertex): (- llo_getField({A},13) -).
To write the sequence-ending instruction vertex (X - an instruction vertex) to (A - an instruction vertex): (- llo_setField({A},13,{X}); -).
To write the jump predecessor linked list (X - a linked list) to (A - an instruction vertex): (- llo_setField({A},14,{X}); -).
To write the jump link (X - an instruction vertex) to (A - an instruction vertex): (- llo_setField({A},15,{X}); -).
To decide what number is the source jump address of (A - an instruction vertex):
let the influence on control flow be the influence on control flow of A;
if the influence on control flow is jump without call or the influence on control flow is exception catch:
let the jump parameter index be the jump parameter index of A;
if the addressing mode of parameter jump parameter index of A is the constant addressing mode:
let the offset be parameter jump parameter index of A;
if the relative jump addressing flag is set in A:
if the offset is not zero and the offset is not one:
increase the offset by the source end address of A;
decide on the offset minus two;
otherwise:
decide on the offset;
decide on zero.
Section "Public Instruction Vertex Accessors and Mutators"
[We give the illusion that all of the data one could find in an operation code record are computed off the operation code: though those data are not writable, they change whenever the operation code does. But in reality, we're caching it all and replacing the whole cache whenever the operation code is written.]
To decide what number is the operation code of (A - an instruction vertex): (- llo_getInt({A}) -).
To write the operation code (C - a number) to (A - an instruction vertex):
copy the shared fields of the record for the operation code C to A.
To decide what text is the I6 assembly name of (A - an instruction vertex):
[It's okay for this to be slow; it's just for debugging.]
let the record be the record for the operation code the operation code of A;
decide on the I6 assembly name of the record.
To decide what number is the parameter limit of (A - an instruction vertex): (- llo_getField({A},1) -).
To decide what number is the parameter mode byte count of (A - an instruction vertex): (- llo_getField({A},2) -).
To decide what number is the load parameter limit of (A - an instruction vertex):
[It's okay for this to be slow; it's rarely used.]
let the record be the record for the operation code the operation code of A;
decide on the load parameter limit of the record.
To decide whether the fallthrough flag is set in (A - an instruction vertex): (- llo_getField({A},3) -).
To decide what influence on control flow is the influence on control flow of (A - an instruction vertex): (- llo_getField({A},4) -).
To decide whether the relative jump addressing flag is set in (A - an instruction vertex): (- llo_getField({A},5) -).
To decide what number is the jump parameter index of (A - an instruction vertex): (- llo_getField({A},6) -).
To decide what number is the source address of (A - an instruction vertex): (- llo_getField({A},7) -).
To decide what number is the source end address of (A - an instruction vertex): (- llo_getField({A},8) -).
To decide what number is the destination offset of (A - an instruction vertex): (- llo_getField({A},9) -).
To decide what number is the destination end offset of (A - an instruction vertex): (- llo_getField({A},10) -).
To decide what instruction vertex is the previous link of (A - an instruction vertex): (- llo_getField({A},11) -).
To decide what instruction vertex is the next link of (A - an instruction vertex): (- llo_getField({A},12) -).
To decide what linked list is the jump predecessor linked list of (A - an instruction vertex): (- ({A}-->14) -).
To decide what instruction vertex is the jump link of (A - an instruction vertex): (- llo_getField({A},15) -).
To establish a jump link from (A - an instruction vertex) to (B - an instruction vertex):
let the old jump link be the jump link of A;
if the old jump link is not null:
remove the first occurrence of the key A from the jump predecessor linked list of the old jump link;
write the jump link B to A;
push the key A onto the jump predecessor linked list of B.
[Reminder: Parameters are numbered from zero.]
To decide what addressing mode is the addressing mode of parameter (P - a number) of (A - an instruction vertex): (- llo_getField({A},16+2*{P}) -).
To write the addressing mode (X - an addressing mode) to parameter (P - a number) of (A - an instruction vertex): (- llo_setField({A},16+2*{P},{X}); -).
To decide what number is parameter (P - a number) of (A - an instruction vertex): (- llo_getField({A},17+2*{P}) -).
To write (X - a number) to parameter (P - a number) of (A - an instruction vertex): (- llo_setField({A},17+2*{P},{X}); -).
To decide whether the shielded flag is set in (A - an instruction vertex): (- llo_getField({A},32) -).
To reset the shielded flag in (A - an instruction vertex): (- llo_setField({A},32,0); -).
To set the shielded flag in (A - an instruction vertex): (- llo_setField({A},32,1); -).
Section "Copying Instruction Vertices"
To copy the operation code and parameters from (A - an instruction vertex) to (B - an instruction vertex):
let the space for parameters be eight times the maximum number of parameters taken by any Glulx operation code;
copy 28 bytes from address (A converted to a number) to address (B converted to a number);
copy the space for parameters bytes from address (A converted to a number plus 64) to address (B converted to a number plus 64).
Chapter "The Instrumentation Scratch Space"
Section "Scratch Space End Points"
[This is the vertex that represents the first instruction to execute in the chunk.]
The scratch space entry vertex is an instruction vertex that varies.
[This is the vertex that represents the first instruction of the chunk, according to our rearrangement. For functions this must end up being the same as the entry vertex, though in the middle of instrumentation it could legally be something else.]
The scratch space beginning vertex is an instruction vertex that varies.
[This is the vertex that represents the last instruction of the chunk, according to our rearrangement.]
The scratch space end vertex is an instruction vertex that varies.
[This is the vertex that represents the first instruction of the last sequence of the chunk, according to our rearrangement.]
The scratch space last sequence-beginning vertex is an instruction vertex that varies.
Section "The Scratch Space Hash Table" - unindexed
[This table maps source addresses to instruction vertices.]
The scratch space hash table is a hash table that varies.
A GRIF setup rule (this is the allocate a hash table for the scratch space rule):
now the scratch space hash table is a new hash table with the GRIF instruction vertex hash table size buckets.
Section "Looking Up Instruction Vertices"
To decide what instruction vertex is the instruction vertex corresponding to source address (A - a number):
decide on the first instruction vertex value matching the key A in the scratch space hash table or an invalid instruction vertex if there are no matches.
Section "Resetting the Scratch Space" - unindexed
To reset the scratch space:
let light deletion possible be whether or not all relevant allocations are accounted for after freeing internal memory allocations to the instruction vertex batch object pool;
let the current instruction vertex be the scratch space beginning vertex;
if the current instruction vertex is not an invalid instruction vertex:
if light deletion possible is true:
while the current instruction vertex is not null:
let the next instruction vertex be the next link of the current instruction vertex;
let the key be the source address of the current instruction vertex;
clear the bucket for the key key in the scratch space hash table;
delete the jump predecessor linked list of the current instruction vertex;
now the current instruction vertex is the next instruction vertex;
otherwise:
while the current instruction vertex is not null:
let the next instruction vertex be the next link of the current instruction vertex;
let the key be the source address of the current instruction vertex;
clear the bucket for the key key in the scratch space hash table;
delete the current instruction vertex;
now the current instruction vertex is the next instruction vertex;
now the scratch space entry vertex is a null instruction vertex;
now the scratch space beginning vertex is a null instruction vertex;
now the scratch space end vertex is a null instruction vertex.
Section "Iteration over the Scratch Space"
To repeat with (I - a nonexisting instruction vertex variable) running through the scratch space begin -- end: (-
for({I}=(+ the scratch space beginning vertex +):{I}:{I}=llo_getField({I},12)) ! field 12 is the next link
-).
Include (-
[ grif_atOrAfter key address offset result;
if(~~address){
return 0;
}
@linkedsearch
key ! the key to search for
4 ! the size of the key in bytes
address ! the address of the first structure to search
offset ! the offset to the key
48 ! the offset to the link
0 ! the options (no need for special options)
result;
return result;
];
-).
To repeat with (I - a nonexisting instruction vertex variable) running through occurrences of the operation code (O - a number) in the scratch space begin -- end: (-
for({I}=grif_atOrAfter({O},(+ the scratch space beginning vertex +),0):{I}:{I}=grif_atOrAfter({O},llo_getField({I},12),0)) ! field 12 is the next link, field 0 is the operation code
-).
To repeat with (I - a nonexisting instruction vertex variable) running through occurrences of (C - an influence on control flow) in the scratch space begin -- end: (-
for({I}=grif_atOrAfter({C},(+ the scratch space beginning vertex +),16):{I}:{I}=grif_atOrAfter({C},llo_getField({I},12),16)) ! field 12 is the next link, field 4 is the influence on control flow
-).
Chapter "Debugging"
Section "Data Structures for Say Phrases" - unindexed
The disassembly label hash table is a hash table that varies.
Section "Data Structure Management for Say Phrases"
To initialize the disassembly label hash table:
unless the disassembly label hash table is an invalid hash table:
fail at initializing the disassembly label hash table twice with no intervening teardown;
let the label count be zero;
now the disassembly label hash table is a new hash table with the GRIF disassembly label hash table size buckets;
repeat with the instruction vertex running through the scratch space:
if the jump predecessor linked list of the instruction vertex is not empty:
increment the label count;
insert the key the instruction vertex and the value the label count into the disassembly label hash table.
To tear down the disassembly label hash table:
if the disassembly label hash table is an invalid hash table:
fail at tearing down the uninitialized disassembly label hash table;
delete the disassembly label hash table;
now the disassembly label hash table is an invalid hash table.
Section "Helper Functions for Partial Say Phrases" - unindexed
To print the I6-like assembly of (A - an instruction vertex), using labels if possible:
say "[the I6 assembly name of A]";
let the parameter limit be the parameter limit of A;
repeat with the parameter index running from zero to the parameter limit:
if the addressing mode of parameter parameter index of A is:
-- the zero-or-discard addressing mode:
say " <zero>";
-- the constant addressing mode:
if using labels if possible and the disassembly label hash table is not an invalid hash table and the parameter index is the jump parameter index of A:
let the linked list vertex be the first match for the key the jump link of A in the disassembly label hash table;
if the linked list vertex is not null:
say " ?L[the number value of the linked list vertex]";
next;
say " [parameter parameter index of A in hexadecimal]";
-- the zero-based-dereference addressing mode:
say " *[parameter parameter index of A in hexadecimal]";
-- the stack addressing mode:
say " <stack>";
-- the call-frame-local addressing mode:
say " locals[bracket][parameter parameter index of A in hexadecimal][close bracket]";
-- the ram-based-dereference addressing mode:
say " *(RAM+[parameter parameter index of A in hexadecimal])";
-- the start-of-vertex addressing mode:
let the reference instruction vertex be parameter parameter index of A converted to an instruction vertex;
let the reference offset be the destination offset of the reference instruction vertex;
say " chunk+[the reference offset in hexadecimal](instruction [the source address of the reference instruction vertex in hexadecimal])";
-- the near-end-of-vertex addressing mode:
let the reference instruction vertex be parameter parameter index of A converted to an instruction vertex;
let the reference offset be the destination end offset of the reference instruction vertex;
say " chunk+[the reference offset minus two in hexadecimal](jump base after [the source address of the reference instruction vertex in hexadecimal])".
Section "Partial Say Phrases for Instructions"
To say the label of (A - an instruction vertex):
if the disassembly label hash table is not the invalid hash table:
let the linked list vertex be the first match for the key A in the disassembly label hash table;
if the linked list vertex is not null:
say ".L[the number value of the linked list vertex]:[line break]".
To say the source range of (A - an instruction vertex):
let the source address be the source address of A;
let the source end address be the source end address of A;
say "[bracket][the source address in hexadecimal]--[the source end address in hexadecimal])".
To say the destination range of (A - an instruction vertex):
let the destination offset be the destination offset of A;
let the destination end offset be the destination end offset of A;
say "[bracket][the destination offset in hexadecimal]--[the destination end offset in hexadecimal])/[bracket][the beginning of instructions in the emitted chunk plus the destination offset in hexadecimal]--[the beginning of instructions in the emitted chunk plus the destination end offset in hexadecimal])".
To say the fallthrough and jump of (A - an instruction vertex):
if the fallthrough flag is set in A:
let the next instruction vertex be the next link of A;
if the next instruction vertex is null:
say "(incomplete,";
otherwise:
say "([the source address of the next instruction vertex in hexadecimal],";
otherwise:
say "(none,";
let the jump link be the jump link of A;
if the jump link is null:
say " none)";
otherwise:
say " [the source address of the jump link in hexadecimal])".
To say the I6-like assembly of (A - an instruction vertex):
print the I6-like assembly of A.
To say the I6-like assembly of (A - an instruction vertex) using labels if possible:
print the I6-like assembly of A, using labels if possible.
Section "The Human-Friendly Form of the Scratch Space"
To say the human-friendly form of (A - an instruction vertex):
say "[the label of A] [the source address of A in hexadecimal] [the I6-like assembly of A using labels if possible][line break]".
To say the human-friendly form of the scratch space:
initialize the disassembly label hash table;
say "[bracket]BEGINNING OF INSTRUCTIONS IN SCRATCH SPACE[close bracket][line break]";
repeat with the instruction vertex running through the scratch space:
say "[the human-friendly form of the instruction vertex]";
say "[bracket]END OF INSTRUCTIONS IN SCRATCH SPACE[close bracket][paragraph break]";
tear down the disassembly label hash table.
Section "The Detailed Human-Friendly Form of the Scratch Space"
[These are really only useful to someone maintaining GRIF or a GRIF extension.]
To say the detailed human-friendly form of (A - an instruction vertex):
say "[the source range of A] [the fallthrough and jump of A] [the I6-like assembly of A][line break]".
To say the detailed human-friendly form of the scratch space:
say "[bracket]BEGINNING OF INSTRUCTIONS IN SCRATCH SPACE[close bracket][line break]";
repeat with the instruction vertex running through the scratch space:
say "[the detailed human-friendly form of the instruction vertex]";
say "[bracket]END OF INSTRUCTIONS IN SCRATCH SPACE[close bracket][paragraph break]".
Section "The Very Detailed Human-Friendly Form of the Scratch Space" - unindexed
[These are really only useful to someone maintaining GRIF.]
To say the very detailed human-friendly form of (A - an instruction vertex):
say "[the source range of A] [the destination range of A] [the fallthrough and jump of A] [the I6-like assembly of A][line break]".