@jhlagado/azm 0.2.5 → 0.2.7
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/dist/src/register-care/boundaryHints.d.ts +1 -0
- package/dist/src/register-care/boundaryHints.js +69 -0
- package/dist/src/register-care/liveness.js +8 -5
- package/dist/src/register-care/profiles.d.ts +6 -1
- package/dist/src/register-care/profiles.js +173 -0
- package/dist/src/register-care/programModel.js +80 -2
- package/dist/src/register-care/summaries.js +15 -2
- package/dist/src/register-care/types.d.ts +2 -0
- package/package.json +1 -1
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import type { RegisterCareInstruction } from './types.js';
|
|
2
2
|
export declare function precedingCServiceName(item: RegisterCareInstruction | undefined): string | undefined;
|
|
3
|
+
export declare function precedingRegisterImmediateValue(item: RegisterCareInstruction | undefined, register: string): number | undefined;
|
|
@@ -9,3 +9,72 @@ export function precedingCServiceName(item) {
|
|
|
9
9
|
}
|
|
10
10
|
return undefined;
|
|
11
11
|
}
|
|
12
|
+
function evaluateKnownConstant(expression, constants) {
|
|
13
|
+
switch (expression.kind) {
|
|
14
|
+
case 'number':
|
|
15
|
+
return expression.value;
|
|
16
|
+
case 'symbol':
|
|
17
|
+
return constants.get(expression.name);
|
|
18
|
+
case 'unary': {
|
|
19
|
+
const value = evaluateKnownConstant(expression.expression, constants);
|
|
20
|
+
if (value === undefined)
|
|
21
|
+
return undefined;
|
|
22
|
+
switch (expression.operator) {
|
|
23
|
+
case '+':
|
|
24
|
+
return value;
|
|
25
|
+
case '-':
|
|
26
|
+
return -value;
|
|
27
|
+
case '~':
|
|
28
|
+
return ~value;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
case 'binary': {
|
|
32
|
+
const left = evaluateKnownConstant(expression.left, constants);
|
|
33
|
+
const right = evaluateKnownConstant(expression.right, constants);
|
|
34
|
+
if (left === undefined || right === undefined)
|
|
35
|
+
return undefined;
|
|
36
|
+
switch (expression.operator) {
|
|
37
|
+
case '+':
|
|
38
|
+
return left + right;
|
|
39
|
+
case '-':
|
|
40
|
+
return left - right;
|
|
41
|
+
case '*':
|
|
42
|
+
return left * right;
|
|
43
|
+
case '/':
|
|
44
|
+
return right === 0 ? undefined : Math.trunc(left / right);
|
|
45
|
+
case '%':
|
|
46
|
+
return right === 0 ? undefined : left % right;
|
|
47
|
+
case '&':
|
|
48
|
+
return left & right;
|
|
49
|
+
case '^':
|
|
50
|
+
return left ^ right;
|
|
51
|
+
case '|':
|
|
52
|
+
return left | right;
|
|
53
|
+
case '<<':
|
|
54
|
+
return left << right;
|
|
55
|
+
case '>>':
|
|
56
|
+
return left >> right;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
case 'byte-function': {
|
|
60
|
+
const value = evaluateKnownConstant(expression.expression, constants);
|
|
61
|
+
if (value === undefined)
|
|
62
|
+
return undefined;
|
|
63
|
+
return expression.function === 'LSB' ? value & 0xff : (value >> 8) & 0xff;
|
|
64
|
+
}
|
|
65
|
+
default:
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export function precedingRegisterImmediateValue(item, register) {
|
|
70
|
+
const instruction = item?.instruction;
|
|
71
|
+
if (!instruction || instruction.mnemonic !== 'ld')
|
|
72
|
+
return undefined;
|
|
73
|
+
if (instruction.target?.kind !== 'reg8' ||
|
|
74
|
+
instruction.target.register !== register.toLowerCase()) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
if (instruction.source.kind !== 'imm')
|
|
78
|
+
return undefined;
|
|
79
|
+
return evaluateKnownConstant(instruction.source.expression, item.constants ?? new Map());
|
|
80
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getZ80InstructionEffect } from '../z80/effects.js';
|
|
2
|
-
import { precedingCServiceName } from './boundaryHints.js';
|
|
2
|
+
import { precedingCServiceName, precedingRegisterImmediateValue } from './boundaryHints.js';
|
|
3
3
|
import { instructionSuccessors, labelIndex } from './controlFlow.js';
|
|
4
|
-
import { rstServiceTargetName, rstTargetName } from './profiles.js';
|
|
4
|
+
import { rstDispatcherServiceTargetNames, rstServiceTargetName, rstTargetName, } from './profiles.js';
|
|
5
5
|
function unique(units) {
|
|
6
6
|
return [...new Set(units)];
|
|
7
7
|
}
|
|
@@ -27,10 +27,13 @@ function boundaryTarget(routine, index, effect) {
|
|
|
27
27
|
}
|
|
28
28
|
if (effect.control.kind === 'rst' && effect.control.vector !== undefined) {
|
|
29
29
|
const target = rstTargetName(effect.control.vector);
|
|
30
|
+
const previous = routine.instructions[index - 1];
|
|
30
31
|
const service = precedingCServiceName(routine.instructions[index - 1]);
|
|
31
|
-
const targets =
|
|
32
|
-
|
|
33
|
-
: [
|
|
32
|
+
const targets = [
|
|
33
|
+
...rstDispatcherServiceTargetNames(effect.control.vector, (register) => precedingRegisterImmediateValue(previous, register)),
|
|
34
|
+
...(service ? [rstServiceTargetName(effect.control.vector, service)] : []),
|
|
35
|
+
target,
|
|
36
|
+
];
|
|
34
37
|
return { targets, conditional: false, subject: target };
|
|
35
38
|
}
|
|
36
39
|
return undefined;
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import type { RoutineSummary } from './types.js';
|
|
1
|
+
import type { RegisterCareUnit, RoutineSummary } from './types.js';
|
|
2
2
|
export interface RegisterCareProfileSummary {
|
|
3
3
|
name: 'mon3';
|
|
4
4
|
rst: Map<number, RoutineSummary>;
|
|
5
5
|
rstServices: Map<string, RoutineSummary>;
|
|
6
|
+
rstDispatchers: Map<number, {
|
|
7
|
+
selector: RegisterCareUnit;
|
|
8
|
+
services: Map<number, RoutineSummary>;
|
|
9
|
+
}>;
|
|
6
10
|
}
|
|
7
11
|
export declare function rstTargetName(vector: number): string;
|
|
8
12
|
export declare function rstServiceTargetName(vector: number, service: string): string;
|
|
13
|
+
export declare function rstDispatcherServiceTargetNames(vector: number, selectorValue: (register: RegisterCareUnit) => number | undefined): string[];
|
|
9
14
|
export declare function getRegisterCareProfile(name: 'mon3' | undefined): RegisterCareProfileSummary | undefined;
|
|
@@ -8,9 +8,166 @@ function normalizeServiceName(raw) {
|
|
|
8
8
|
export function rstServiceTargetName(vector, service) {
|
|
9
9
|
return `${rstTargetName(vector)}:${normalizeServiceName(service)}`;
|
|
10
10
|
}
|
|
11
|
+
function mon3ApiTargetName(api, name) {
|
|
12
|
+
return `MON3_API_${api}_${name.replace(/[^A-Za-z0-9_]/gu, '').toUpperCase()}`;
|
|
13
|
+
}
|
|
14
|
+
function conservativeMon3ApiSummary(api, name) {
|
|
15
|
+
return {
|
|
16
|
+
name: mon3ApiTargetName(api, name),
|
|
17
|
+
mayRead: ['A', 'B', 'C', 'D', 'E', 'H', 'L', ...FLAG_UNITS],
|
|
18
|
+
mayWrite: ['A', 'B', 'C', 'D', 'E', 'H', 'L', ...FLAG_UNITS],
|
|
19
|
+
mayOutput: [],
|
|
20
|
+
preserved: [],
|
|
21
|
+
valueRelations: [],
|
|
22
|
+
stackBalanced: true,
|
|
23
|
+
hasUnknownStackEffect: false,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function mon3ApiServices(overrides) {
|
|
27
|
+
const names = [
|
|
28
|
+
'SOFTWARE_ID',
|
|
29
|
+
'VERSION_ID',
|
|
30
|
+
'PRE_INIT',
|
|
31
|
+
'BEEP_ALWAYS',
|
|
32
|
+
'CONV_A_TO_SEG',
|
|
33
|
+
'REG_A_TO_ASCII',
|
|
34
|
+
'ASCII_TO_SEGMENT',
|
|
35
|
+
'STRING_COMPARE',
|
|
36
|
+
'HL_TO_STRING',
|
|
37
|
+
'A_TO_STRING',
|
|
38
|
+
'SCAN_SEGMENTS',
|
|
39
|
+
'DISPLAY_ERROR',
|
|
40
|
+
'LCD_BUSY',
|
|
41
|
+
'STRING_TO_LCD',
|
|
42
|
+
'CHAR_TO_LCD',
|
|
43
|
+
'COMMAND_TO_LCD',
|
|
44
|
+
'SCAN_KEYS',
|
|
45
|
+
'SCAN_KEYS_WAIT',
|
|
46
|
+
'MATRIX_SCAN',
|
|
47
|
+
'JOYSTICK_SCAN',
|
|
48
|
+
'SERIAL_ENABLE',
|
|
49
|
+
'SERIAL_DISABLE',
|
|
50
|
+
'TX_BYTE',
|
|
51
|
+
'RX_BYTE',
|
|
52
|
+
'INTEL_HEX_LOAD',
|
|
53
|
+
'SEND_TO_SERIAL_API',
|
|
54
|
+
'RECEIVE_FROM_SERIAL_API',
|
|
55
|
+
'SEND_ASSEMBLY_API',
|
|
56
|
+
'SEND_HEX_API',
|
|
57
|
+
'GEN_DATA_DUMP',
|
|
58
|
+
'CHECK_START_END',
|
|
59
|
+
'MENU_DRIVER',
|
|
60
|
+
'PARAM_DRIVER',
|
|
61
|
+
'TIME_DELAY',
|
|
62
|
+
'PLAY_NOTE',
|
|
63
|
+
'PLAY_TUNE',
|
|
64
|
+
'PLAY_TUNE_MENU',
|
|
65
|
+
'GET_CAPS',
|
|
66
|
+
'GET_SHADOW',
|
|
67
|
+
'GET_PROTECT',
|
|
68
|
+
'GET_EXPAND',
|
|
69
|
+
'SET_CAPS',
|
|
70
|
+
'SET_SHADOW',
|
|
71
|
+
'SET_PROTECT',
|
|
72
|
+
'SET_EXPAND',
|
|
73
|
+
'STRING_TO_SERIAL',
|
|
74
|
+
'RTC_API',
|
|
75
|
+
'MENU_POP',
|
|
76
|
+
'TOGGLE_CAPS',
|
|
77
|
+
'RANDOM',
|
|
78
|
+
'SET_DIS_START',
|
|
79
|
+
'GET_DIS_NEXT',
|
|
80
|
+
'GET_DISASSEMBLY',
|
|
81
|
+
'MATRIX_SCAN_ASCII',
|
|
82
|
+
'PARSE_MATRIX_SCAN',
|
|
83
|
+
'LCD_CONFIRM',
|
|
84
|
+
'GET_GLCD_TERM',
|
|
85
|
+
'SET_GLCD_TERM',
|
|
86
|
+
'LOAD_FROM_DISK',
|
|
87
|
+
'OPEN_FILE',
|
|
88
|
+
'READ_SECTOR',
|
|
89
|
+
'WRITE_SECTOR',
|
|
90
|
+
'RGB_SCAN',
|
|
91
|
+
];
|
|
92
|
+
return new Map(names.map((serviceName, api) => [
|
|
93
|
+
api,
|
|
94
|
+
overrides.get(api) ?? conservativeMon3ApiSummary(api, serviceName),
|
|
95
|
+
]));
|
|
96
|
+
}
|
|
97
|
+
export function rstDispatcherServiceTargetNames(vector, selectorValue) {
|
|
98
|
+
const mon3 = getRegisterCareProfile('mon3');
|
|
99
|
+
const dispatcher = mon3?.rstDispatchers.get(vector);
|
|
100
|
+
if (dispatcher === undefined)
|
|
101
|
+
return [];
|
|
102
|
+
const value = selectorValue(dispatcher.selector);
|
|
103
|
+
if (value === undefined)
|
|
104
|
+
return [];
|
|
105
|
+
const service = dispatcher.services.get(value);
|
|
106
|
+
return service ? [service.name] : [];
|
|
107
|
+
}
|
|
11
108
|
export function getRegisterCareProfile(name) {
|
|
12
109
|
if (name !== 'mon3')
|
|
13
110
|
return undefined;
|
|
111
|
+
const matrixScan = {
|
|
112
|
+
name: mon3ApiTargetName(18, 'MATRIX_SCAN'),
|
|
113
|
+
mayRead: ['C'],
|
|
114
|
+
mayWrite: ['A', 'B', 'C', 'D', 'E', 'H', 'L', ...FLAG_UNITS],
|
|
115
|
+
mayOutput: ['D', 'E', 'zero'],
|
|
116
|
+
preserved: [],
|
|
117
|
+
valueRelations: [{ out: ['D', 'E', 'zero'], from: [] }],
|
|
118
|
+
stackBalanced: true,
|
|
119
|
+
hasUnknownStackEffect: false,
|
|
120
|
+
};
|
|
121
|
+
const stringToLcd = {
|
|
122
|
+
name: mon3ApiTargetName(13, 'STRING_TO_LCD'),
|
|
123
|
+
mayRead: ['C', 'H', 'L'],
|
|
124
|
+
mayWrite: ['A', 'H', 'L', ...FLAG_UNITS],
|
|
125
|
+
mayOutput: [],
|
|
126
|
+
preserved: ['B', 'C', 'D', 'E'],
|
|
127
|
+
valueRelations: [],
|
|
128
|
+
stackBalanced: true,
|
|
129
|
+
hasUnknownStackEffect: false,
|
|
130
|
+
};
|
|
131
|
+
const charToLcd = {
|
|
132
|
+
name: mon3ApiTargetName(14, 'CHAR_TO_LCD'),
|
|
133
|
+
mayRead: ['A', 'C'],
|
|
134
|
+
mayWrite: [],
|
|
135
|
+
mayOutput: [],
|
|
136
|
+
preserved: ['A', 'B', 'C', 'D', 'E', 'H', 'L', ...FLAG_UNITS],
|
|
137
|
+
valueRelations: [],
|
|
138
|
+
stackBalanced: true,
|
|
139
|
+
hasUnknownStackEffect: false,
|
|
140
|
+
};
|
|
141
|
+
const commandToLcd = {
|
|
142
|
+
name: mon3ApiTargetName(15, 'COMMAND_TO_LCD'),
|
|
143
|
+
mayRead: ['B', 'C'],
|
|
144
|
+
mayWrite: [],
|
|
145
|
+
mayOutput: [],
|
|
146
|
+
preserved: ['A', 'B', 'C', 'D', 'E', 'H', 'L', ...FLAG_UNITS],
|
|
147
|
+
valueRelations: [],
|
|
148
|
+
stackBalanced: true,
|
|
149
|
+
hasUnknownStackEffect: false,
|
|
150
|
+
};
|
|
151
|
+
const scanKeys = {
|
|
152
|
+
name: mon3ApiTargetName(16, 'SCAN_KEYS'),
|
|
153
|
+
mayRead: ['C'],
|
|
154
|
+
mayWrite: ['A', 'carry', 'zero'],
|
|
155
|
+
mayOutput: ['A', 'carry', 'zero'],
|
|
156
|
+
preserved: ['B', 'C', 'H', 'L'],
|
|
157
|
+
valueRelations: [{ out: ['A', 'carry', 'zero'], from: [] }],
|
|
158
|
+
stackBalanced: true,
|
|
159
|
+
hasUnknownStackEffect: false,
|
|
160
|
+
};
|
|
161
|
+
const parseMatrixScan = {
|
|
162
|
+
name: mon3ApiTargetName(54, 'PARSE_MATRIX_SCAN'),
|
|
163
|
+
mayRead: ['C', 'D', 'E', 'zero'],
|
|
164
|
+
mayWrite: ['A', 'B', 'C', 'H', 'L', 'carry', 'sign', 'parity', 'halfCarry'],
|
|
165
|
+
mayOutput: ['A', 'carry'],
|
|
166
|
+
preserved: ['D', 'E'],
|
|
167
|
+
valueRelations: [{ out: ['A', 'carry'], from: ['D', 'E', 'zero'] }],
|
|
168
|
+
stackBalanced: true,
|
|
169
|
+
hasUnknownStackEffect: false,
|
|
170
|
+
};
|
|
14
171
|
return {
|
|
15
172
|
name: 'mon3',
|
|
16
173
|
rst: new Map([
|
|
@@ -43,5 +200,21 @@ export function getRegisterCareProfile(name) {
|
|
|
43
200
|
},
|
|
44
201
|
],
|
|
45
202
|
]),
|
|
203
|
+
rstDispatchers: new Map([
|
|
204
|
+
[
|
|
205
|
+
0x10,
|
|
206
|
+
{
|
|
207
|
+
selector: 'C',
|
|
208
|
+
services: mon3ApiServices(new Map([
|
|
209
|
+
[13, stringToLcd],
|
|
210
|
+
[14, charToLcd],
|
|
211
|
+
[15, commandToLcd],
|
|
212
|
+
[16, scanKeys],
|
|
213
|
+
[18, matrixScan],
|
|
214
|
+
[54, parseMatrixScan],
|
|
215
|
+
])),
|
|
216
|
+
},
|
|
217
|
+
],
|
|
218
|
+
]),
|
|
46
219
|
};
|
|
47
220
|
}
|
|
@@ -4,6 +4,80 @@ function isGlobalLabel(name) {
|
|
|
4
4
|
function routineNameFromExpression(expression) {
|
|
5
5
|
return expression.kind === 'symbol' ? expression.name : undefined;
|
|
6
6
|
}
|
|
7
|
+
function evaluateConstantExpression(expression, constants) {
|
|
8
|
+
switch (expression.kind) {
|
|
9
|
+
case 'number':
|
|
10
|
+
return expression.value;
|
|
11
|
+
case 'symbol':
|
|
12
|
+
return constants.get(expression.name);
|
|
13
|
+
case 'unary': {
|
|
14
|
+
const value = evaluateConstantExpression(expression.expression, constants);
|
|
15
|
+
if (value === undefined)
|
|
16
|
+
return undefined;
|
|
17
|
+
switch (expression.operator) {
|
|
18
|
+
case '+':
|
|
19
|
+
return value;
|
|
20
|
+
case '-':
|
|
21
|
+
return -value;
|
|
22
|
+
case '~':
|
|
23
|
+
return ~value;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
case 'binary': {
|
|
27
|
+
const left = evaluateConstantExpression(expression.left, constants);
|
|
28
|
+
const right = evaluateConstantExpression(expression.right, constants);
|
|
29
|
+
if (left === undefined || right === undefined)
|
|
30
|
+
return undefined;
|
|
31
|
+
switch (expression.operator) {
|
|
32
|
+
case '+':
|
|
33
|
+
return left + right;
|
|
34
|
+
case '-':
|
|
35
|
+
return left - right;
|
|
36
|
+
case '*':
|
|
37
|
+
return left * right;
|
|
38
|
+
case '/':
|
|
39
|
+
return right === 0 ? undefined : Math.trunc(left / right);
|
|
40
|
+
case '%':
|
|
41
|
+
return right === 0 ? undefined : left % right;
|
|
42
|
+
case '&':
|
|
43
|
+
return left & right;
|
|
44
|
+
case '^':
|
|
45
|
+
return left ^ right;
|
|
46
|
+
case '|':
|
|
47
|
+
return left | right;
|
|
48
|
+
case '<<':
|
|
49
|
+
return left << right;
|
|
50
|
+
case '>>':
|
|
51
|
+
return left >> right;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
case 'byte-function': {
|
|
55
|
+
const value = evaluateConstantExpression(expression.expression, constants);
|
|
56
|
+
if (value === undefined)
|
|
57
|
+
return undefined;
|
|
58
|
+
return expression.function === 'LSB' ? value & 0xff : (value >> 8) & 0xff;
|
|
59
|
+
}
|
|
60
|
+
default:
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function collectConstants(items) {
|
|
65
|
+
const constants = new Map();
|
|
66
|
+
let changed = true;
|
|
67
|
+
while (changed) {
|
|
68
|
+
changed = false;
|
|
69
|
+
for (const item of items) {
|
|
70
|
+
if (item.kind !== 'equ' || constants.has(item.name))
|
|
71
|
+
continue;
|
|
72
|
+
const value = evaluateConstantExpression(item.expression, constants);
|
|
73
|
+
if (value === undefined)
|
|
74
|
+
continue;
|
|
75
|
+
constants.set(item.name, value);
|
|
76
|
+
changed = true;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return constants;
|
|
80
|
+
}
|
|
7
81
|
function instructionCallTarget(item) {
|
|
8
82
|
if (item.kind !== 'instruction')
|
|
9
83
|
return undefined;
|
|
@@ -28,13 +102,14 @@ function instructionTailJumpTarget(item, entryNames) {
|
|
|
28
102
|
return undefined;
|
|
29
103
|
return target;
|
|
30
104
|
}
|
|
31
|
-
function toInstruction(item, labels) {
|
|
105
|
+
function toInstruction(item, labels, constants) {
|
|
32
106
|
return {
|
|
33
107
|
instruction: item.instruction,
|
|
34
108
|
file: item.span.sourceName,
|
|
35
109
|
line: item.span.line,
|
|
36
110
|
column: item.span.column,
|
|
37
111
|
labels: [...labels],
|
|
112
|
+
constants,
|
|
38
113
|
};
|
|
39
114
|
}
|
|
40
115
|
function pushDirectBoundary(boundaries, target, subject, file, line, column) {
|
|
@@ -43,6 +118,7 @@ function pushDirectBoundary(boundaries, target, subject, file, line, column) {
|
|
|
43
118
|
export function buildRegisterCareProgramModel(items) {
|
|
44
119
|
const routines = [];
|
|
45
120
|
const directCalls = [];
|
|
121
|
+
const constants = collectConstants(items);
|
|
46
122
|
const filesWithEntryLabels = new Set(items
|
|
47
123
|
.filter((item) => item.kind === 'label')
|
|
48
124
|
.filter((item) => item.isEntry === true)
|
|
@@ -73,6 +149,7 @@ export function buildRegisterCareProgramModel(items) {
|
|
|
73
149
|
labels: [...labels],
|
|
74
150
|
entryLabels: [...entryLabels],
|
|
75
151
|
instructions: [],
|
|
152
|
+
constants,
|
|
76
153
|
span: {
|
|
77
154
|
file: sourceName ?? '',
|
|
78
155
|
start: { line: routineStartLine, column: routineStartColumn ?? 1 },
|
|
@@ -89,6 +166,7 @@ export function buildRegisterCareProgramModel(items) {
|
|
|
89
166
|
labels: [...labels],
|
|
90
167
|
entryLabels: [...entryLabels],
|
|
91
168
|
instructions: [...instructions],
|
|
169
|
+
constants,
|
|
92
170
|
span: {
|
|
93
171
|
file: sourceName ?? '',
|
|
94
172
|
start: { line: routineStartLine, column: routineStartColumn ?? 1 },
|
|
@@ -121,7 +199,7 @@ export function buildRegisterCareProgramModel(items) {
|
|
|
121
199
|
if (item.span.sourceName !== sourceName) {
|
|
122
200
|
continue;
|
|
123
201
|
}
|
|
124
|
-
instructions.push(toInstruction(item, labels));
|
|
202
|
+
instructions.push(toInstruction(item, labels, constants));
|
|
125
203
|
const directTarget = instructionCallTarget(item);
|
|
126
204
|
if (directTarget !== undefined) {
|
|
127
205
|
pushDirectBoundary(directCalls, directTarget, `CALL ${directTarget}`, item.span.sourceName, item.span.line, item.span.column);
|
|
@@ -24,7 +24,13 @@ export function buildProfileSummaries(profileName) {
|
|
|
24
24
|
if (profile === undefined) {
|
|
25
25
|
return [];
|
|
26
26
|
}
|
|
27
|
-
return [
|
|
27
|
+
return [
|
|
28
|
+
...profile.rst.values(),
|
|
29
|
+
...profile.rstServices.values(),
|
|
30
|
+
...[...profile.rstDispatchers.values()].flatMap((dispatcher) => [
|
|
31
|
+
...dispatcher.services.values(),
|
|
32
|
+
]),
|
|
33
|
+
];
|
|
28
34
|
}
|
|
29
35
|
export function buildProfileSummaryLookup(profileName) {
|
|
30
36
|
const profile = getRegisterCareProfile(profileName);
|
|
@@ -37,6 +43,11 @@ export function buildProfileSummaryLookup(profileName) {
|
|
|
37
43
|
for (const summary of profile.rstServices.values()) {
|
|
38
44
|
out.set(summary.name, summary);
|
|
39
45
|
}
|
|
46
|
+
for (const dispatcher of profile.rstDispatchers.values()) {
|
|
47
|
+
for (const summary of dispatcher.services.values()) {
|
|
48
|
+
out.set(summary.name, summary);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
40
51
|
return out;
|
|
41
52
|
}
|
|
42
53
|
export function routineNames(routines) {
|
|
@@ -44,7 +55,9 @@ export function routineNames(routines) {
|
|
|
44
55
|
}
|
|
45
56
|
export function buildSummaries(routines, contractMap, profileSummaries = []) {
|
|
46
57
|
const names = routineNameSet(routines);
|
|
47
|
-
const routineSummaries = inferRoutineSummariesToFixedPoint([...routines], contractMap, names, [
|
|
58
|
+
const routineSummaries = inferRoutineSummariesToFixedPoint([...routines], contractMap, names, [
|
|
59
|
+
...profileSummaries,
|
|
60
|
+
]);
|
|
48
61
|
const summaries = routineSummaries.map((item) => item.summary);
|
|
49
62
|
return summariesWithExternalContracts(summaries, contractMap, names);
|
|
50
63
|
}
|
|
@@ -44,12 +44,14 @@ export interface RegisterCareInstruction {
|
|
|
44
44
|
line: number;
|
|
45
45
|
column: number;
|
|
46
46
|
labels: string[];
|
|
47
|
+
constants?: ReadonlyMap<string, number>;
|
|
47
48
|
}
|
|
48
49
|
export interface RegisterCareRoutine {
|
|
49
50
|
name: string;
|
|
50
51
|
labels: string[];
|
|
51
52
|
entryLabels: string[];
|
|
52
53
|
instructions: RegisterCareInstruction[];
|
|
54
|
+
constants?: ReadonlyMap<string, number>;
|
|
53
55
|
span: {
|
|
54
56
|
file: string;
|
|
55
57
|
start: {
|