@specy/x86 2.1.0 → 2.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.md +39 -0
- package/dist/index.d.mts +387 -231
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +605 -129
- package/dist/index.mjs.map +1 -1
- package/dist/wasm/nasm.d.mts +47 -0
- package/dist/wasm/nasm.mjs +2 -0
- package/dist/wasm/nasm.wasm +0 -0
- package/package.json +2 -1
- package/dist/assets/assemblers/nasm.3.00.elf +0 -0
package/dist/index.d.mts
CHANGED
|
@@ -5,78 +5,173 @@ declare function toResourceUrl(source: string | URL): URL;
|
|
|
5
5
|
declare function readResourceBytes(source: ResourceSource): Promise<Uint8Array>;
|
|
6
6
|
declare function defaultResourceUrl(relativePath: string, baseUrl: string): URL;
|
|
7
7
|
//#endregion
|
|
8
|
-
//#region src/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
//#region src/interface.d.ts
|
|
9
|
+
type StatusRegister = {
|
|
10
|
+
name: string;
|
|
11
|
+
value: number;
|
|
12
|
+
prev: number;
|
|
13
|
+
};
|
|
14
|
+
type DiagnosticSeverity = 'error' | 'warning';
|
|
15
|
+
type MonacoError = {
|
|
16
|
+
/** Project-relative source path when checking a virtual Project. */file?: string;
|
|
17
|
+
lineIndex: number;
|
|
18
|
+
column: number;
|
|
19
|
+
line: {
|
|
20
|
+
line: string;
|
|
21
|
+
line_index: number;
|
|
22
|
+
};
|
|
23
|
+
message: string;
|
|
24
|
+
formatted: string; /** A warning still assembles; only an error stops the build. Absent means error. */
|
|
25
|
+
severity?: DiagnosticSeverity; /** The assembler's own name for the warning, such as `label-orphan`. */
|
|
26
|
+
code?: string; /** Help beyond what the assembler said, when this diagnostic has a known explanation. */
|
|
27
|
+
hint?: string;
|
|
28
|
+
};
|
|
29
|
+
type StackFrame = {
|
|
30
|
+
name: string;
|
|
31
|
+
address: bigint;
|
|
32
|
+
destination: bigint;
|
|
33
|
+
sp: bigint;
|
|
15
34
|
line: number;
|
|
16
|
-
|
|
35
|
+
file?: string;
|
|
36
|
+
color: string;
|
|
37
|
+
};
|
|
38
|
+
type RegisterHex = [hi: string, lo: string];
|
|
39
|
+
declare enum RegisterSize {
|
|
40
|
+
Byte = 1,
|
|
41
|
+
Word = 2,
|
|
42
|
+
Long = 4,
|
|
43
|
+
Double = 8
|
|
17
44
|
}
|
|
18
|
-
type
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
diagnosticsParser?: DiagnosticsParser;
|
|
24
|
-
binaries: {
|
|
25
|
-
assembler: Binary;
|
|
26
|
-
linker?: Binary;
|
|
45
|
+
type ExecutionStep = {
|
|
46
|
+
mutations: MutationOperation[];
|
|
47
|
+
pc: number;
|
|
48
|
+
old_ccr: {
|
|
49
|
+
bits: number;
|
|
27
50
|
};
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
GNU_trunk: {
|
|
31
|
-
id: string;
|
|
32
|
-
displayName: string;
|
|
33
|
-
description: string;
|
|
34
|
-
diagnosticsParser: typeof gnuDiagnostics;
|
|
35
|
-
binaries: {
|
|
36
|
-
assembler: {
|
|
37
|
-
file: URL;
|
|
38
|
-
commands: string;
|
|
39
|
-
};
|
|
40
|
-
linker: {
|
|
41
|
-
file: URL;
|
|
42
|
-
commands: string;
|
|
43
|
-
};
|
|
44
|
-
};
|
|
51
|
+
new_ccr: {
|
|
52
|
+
bits: number;
|
|
45
53
|
};
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
};
|
|
56
|
-
};
|
|
54
|
+
line: number;
|
|
55
|
+
file?: string;
|
|
56
|
+
};
|
|
57
|
+
type MutationOperation = {
|
|
58
|
+
type: 'WriteRegister';
|
|
59
|
+
value: {
|
|
60
|
+
register: string;
|
|
61
|
+
old: bigint;
|
|
62
|
+
size: RegisterSize;
|
|
57
63
|
};
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
commands: string;
|
|
71
|
-
};
|
|
72
|
-
};
|
|
64
|
+
} | {
|
|
65
|
+
type: 'WriteMemory';
|
|
66
|
+
value: {
|
|
67
|
+
address: bigint;
|
|
68
|
+
old: bigint;
|
|
69
|
+
size: RegisterSize;
|
|
70
|
+
};
|
|
71
|
+
} | {
|
|
72
|
+
type: 'WriteMemoryBytes';
|
|
73
|
+
value: {
|
|
74
|
+
address: bigint;
|
|
75
|
+
old: number[];
|
|
73
76
|
};
|
|
77
|
+
} | {
|
|
78
|
+
type: 'PopCallStack';
|
|
79
|
+
value: {
|
|
80
|
+
to: bigint;
|
|
81
|
+
from: bigint;
|
|
82
|
+
};
|
|
83
|
+
} | {
|
|
84
|
+
type: 'PushCallStack';
|
|
85
|
+
value: {
|
|
86
|
+
to: bigint;
|
|
87
|
+
from: bigint;
|
|
88
|
+
};
|
|
89
|
+
} | {
|
|
90
|
+
type: 'Other';
|
|
91
|
+
value: string;
|
|
74
92
|
};
|
|
75
|
-
type
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
93
|
+
type EmulatorDecoration = {
|
|
94
|
+
type: 'below-line';
|
|
95
|
+
note?: string;
|
|
96
|
+
belowLine: number;
|
|
97
|
+
md: string;
|
|
98
|
+
};
|
|
99
|
+
type CompilationError = {
|
|
100
|
+
type: 'raw';
|
|
101
|
+
message: string;
|
|
102
|
+
};
|
|
103
|
+
declare enum EmulatorStatus {
|
|
104
|
+
Terminated = 0,
|
|
105
|
+
Running = 1,
|
|
106
|
+
WaitingForInput = 2,
|
|
107
|
+
NotReady = 3
|
|
108
|
+
}
|
|
109
|
+
type Instruction = {
|
|
110
|
+
address: bigint;
|
|
111
|
+
lineNumber: number;
|
|
112
|
+
file?: string;
|
|
113
|
+
size?: number;
|
|
114
|
+
bytes?: Uint8Array;
|
|
115
|
+
code: string;
|
|
116
|
+
};
|
|
117
|
+
type EmulatorConfig<R extends string> = {
|
|
118
|
+
systemSize: RegisterSize;
|
|
119
|
+
registerNames: R[];
|
|
120
|
+
endianness?: 'little' | 'big';
|
|
121
|
+
hiddenRegisters?: R[];
|
|
122
|
+
};
|
|
123
|
+
declare abstract class BaseEmulator<T, R extends string, CompileResult = {
|
|
124
|
+
ok: true;
|
|
125
|
+
} | {
|
|
126
|
+
ok: false;
|
|
127
|
+
errors: CompilationError[];
|
|
128
|
+
report: string;
|
|
129
|
+
}> {
|
|
130
|
+
protected _registerNames: R[];
|
|
131
|
+
protected _systemSize: RegisterSize;
|
|
132
|
+
protected _endianness: 'little' | 'big';
|
|
133
|
+
constructor(options: EmulatorConfig<R>);
|
|
134
|
+
getSystemSize(): RegisterSize;
|
|
135
|
+
getEndianness(): 'little' | 'big';
|
|
136
|
+
getRegisterNames(): R[];
|
|
137
|
+
abstract initialize(undoSize: number): void;
|
|
138
|
+
abstract getCompiledCode(): {
|
|
139
|
+
decorations: EmulatorDecoration[];
|
|
140
|
+
code: string;
|
|
141
|
+
};
|
|
142
|
+
abstract dispose(): void;
|
|
143
|
+
abstract stringifyError(error: unknown): string;
|
|
144
|
+
abstract compile(code: string): Promise<CompileResult>;
|
|
145
|
+
abstract checkCode(code: string): Promise<MonacoError[]>;
|
|
146
|
+
abstract undo(): void;
|
|
147
|
+
abstract canUndo(): boolean;
|
|
148
|
+
abstract step(): Promise<{
|
|
149
|
+
terminated: boolean;
|
|
150
|
+
}>;
|
|
151
|
+
abstract getStatus(): EmulatorStatus;
|
|
152
|
+
abstract writeMemoryBytes(address: bigint, data: Uint8Array): void;
|
|
153
|
+
abstract readMemoryBytes(address: bigint, length: bigint): Uint8Array;
|
|
154
|
+
abstract getNextInstruction(): Instruction | null;
|
|
155
|
+
abstract getUndoHistory(max: number): ExecutionStep[];
|
|
156
|
+
abstract getPc(): bigint;
|
|
157
|
+
abstract getSp(): bigint;
|
|
158
|
+
abstract getFlags(): {
|
|
159
|
+
name: string;
|
|
160
|
+
value: number;
|
|
161
|
+
prev?: number;
|
|
162
|
+
}[];
|
|
163
|
+
abstract getCallStack(): StackFrame[];
|
|
164
|
+
abstract getInstructionAt(address: bigint): Instruction | null;
|
|
165
|
+
abstract getRegisterValues(): bigint[];
|
|
166
|
+
abstract getRegisterValuesRecord(): Record<R, bigint>;
|
|
167
|
+
abstract getRegisterValue(register: R, size?: RegisterSize): bigint;
|
|
168
|
+
abstract setRegisterValue(register: R, value: bigint, size?: RegisterSize): void;
|
|
169
|
+
abstract hasTerminated(): boolean;
|
|
170
|
+
abstract run(limit?: number, breakpoints?: Array<number | {
|
|
171
|
+
path: string;
|
|
172
|
+
line: number;
|
|
173
|
+
}>): Promise<EmulatorStatus>;
|
|
174
|
+
}
|
|
80
175
|
//#endregion
|
|
81
176
|
//#region src/callbacks.d.ts
|
|
82
177
|
type MaybePromise<T> = T | PromiseLike<T>;
|
|
@@ -110,7 +205,9 @@ type StopReason = {
|
|
|
110
205
|
type X86CompilationDiagnostic = {
|
|
111
206
|
line: number;
|
|
112
207
|
error: string; /** Project-relative source path when compiling a virtual Project. */
|
|
113
|
-
file?: string;
|
|
208
|
+
file?: string; /** A warning still assembles; only an error stops the build. */
|
|
209
|
+
severity: DiagnosticSeverity; /** The assembler's own name for the warning, such as `label-orphan`. */
|
|
210
|
+
warningClass?: string;
|
|
114
211
|
};
|
|
115
212
|
type X86ProjectFile = string | Uint8Array;
|
|
116
213
|
type X86Project = {
|
|
@@ -122,13 +219,20 @@ type X86SourceLocation = {
|
|
|
122
219
|
line: number;
|
|
123
220
|
};
|
|
124
221
|
type X86Breakpoint = number | X86SourceLocation;
|
|
222
|
+
/**
|
|
223
|
+
* `diagnostics` carries everything the assembler said, warnings included - a
|
|
224
|
+
* successful build routinely has some, and they are the most useful thing it
|
|
225
|
+
* produces. `errors` is the subset that stopped the build.
|
|
226
|
+
*/
|
|
125
227
|
type X86CompileResult = {
|
|
126
228
|
ok: true;
|
|
127
229
|
report: string;
|
|
230
|
+
diagnostics: X86CompilationDiagnostic[];
|
|
128
231
|
} | {
|
|
129
232
|
ok: false;
|
|
130
233
|
errors: X86CompilationDiagnostic[];
|
|
131
234
|
report: string;
|
|
235
|
+
diagnostics: X86CompilationDiagnostic[];
|
|
132
236
|
};
|
|
133
237
|
type X86EmulatorEventMap = {
|
|
134
238
|
stateChange: {
|
|
@@ -148,6 +252,152 @@ type X86EmulatorEventMap = {
|
|
|
148
252
|
type X86EmulatorEventName = keyof X86EmulatorEventMap;
|
|
149
253
|
type X86EmulatorEventHandler<T extends X86EmulatorEventName> = (event: X86EmulatorEventMap[T]) => MaybePromise<void>;
|
|
150
254
|
//#endregion
|
|
255
|
+
//#region src/wasm-assembler.d.ts
|
|
256
|
+
/**
|
|
257
|
+
* An assembler that runs as its own WebAssembly module rather than as an x86-64
|
|
258
|
+
* ELF interpreted by blink. Blink costs roughly 1.2s of startup plus 14ms per
|
|
259
|
+
* line of source for NASM; the same work in its own module takes single-digit
|
|
260
|
+
* milliseconds, and produces byte-identical output.
|
|
261
|
+
*
|
|
262
|
+
* The object files come back as bytes for the caller to stage wherever the
|
|
263
|
+
* linker expects them, so the linker can keep running inside blink unchanged.
|
|
264
|
+
*/
|
|
265
|
+
interface WasmAssembler {
|
|
266
|
+
assemble(project: X86Project): Promise<WasmAssemblyResult>;
|
|
267
|
+
}
|
|
268
|
+
/** One translation unit's object, and the Project File it was assembled from. */
|
|
269
|
+
type WasmAssemblyUnit = {
|
|
270
|
+
path: string;
|
|
271
|
+
object: Uint8Array;
|
|
272
|
+
};
|
|
273
|
+
type WasmAssemblyResult = {
|
|
274
|
+
/** The assembler's exit status: 0 when every translation unit assembled. */status: number; /** What it wrote to stdout, verbatim. */
|
|
275
|
+
stdout: string; /** What it wrote to stderr, verbatim - the diagnostics a parser reads. */
|
|
276
|
+
stderr: string;
|
|
277
|
+
/**
|
|
278
|
+
* The objects to link, Entry first. Empty when any translation unit failed:
|
|
279
|
+
* a partial link would report missing symbols that are only missing because
|
|
280
|
+
* the File defining them is the one that did not assemble.
|
|
281
|
+
*/
|
|
282
|
+
units: WasmAssemblyUnit[]; /** The Entry's object, or null when the assembly failed. */
|
|
283
|
+
object: Uint8Array | null;
|
|
284
|
+
};
|
|
285
|
+
//#endregion
|
|
286
|
+
//#region src/assemblers.d.ts
|
|
287
|
+
interface Binary {
|
|
288
|
+
file: ResourceSource;
|
|
289
|
+
commands: string;
|
|
290
|
+
}
|
|
291
|
+
interface LinkerBinary {
|
|
292
|
+
file: ResourceSource;
|
|
293
|
+
/**
|
|
294
|
+
* The command that links however many objects the Project's translation units produced. Every
|
|
295
|
+
* path it is given is one this package generated, so none of them needs escaping.
|
|
296
|
+
*/
|
|
297
|
+
link(objects: readonly string[]): string;
|
|
298
|
+
}
|
|
299
|
+
interface DiagnosticLine {
|
|
300
|
+
file?: string;
|
|
301
|
+
line: number;
|
|
302
|
+
error: string;
|
|
303
|
+
/** A warning still assembles; only an error stops the build. */
|
|
304
|
+
severity: DiagnosticSeverity;
|
|
305
|
+
/**
|
|
306
|
+
* NASM's own name for the warning, taken from the `[-w+label-orphan]` tag it
|
|
307
|
+
* appends. It is a stable identifier for the kind of mistake, which is what
|
|
308
|
+
* an explanation can be keyed on.
|
|
309
|
+
*/
|
|
310
|
+
warningClass?: string;
|
|
311
|
+
}
|
|
312
|
+
type DiagnosticsParser = (assemblerLogs: string) => DiagnosticLine[];
|
|
313
|
+
interface AssemblerMode {
|
|
314
|
+
id: string;
|
|
315
|
+
displayName: string;
|
|
316
|
+
description: string;
|
|
317
|
+
diagnosticsParser?: DiagnosticsParser;
|
|
318
|
+
binaries: {
|
|
319
|
+
/**
|
|
320
|
+
* The assembler as an x86-64 ELF for blink to interpret. Absent when
|
|
321
|
+
* `wasmAssembler` is set, which runs the assembler as its own module
|
|
322
|
+
* instead - far faster, but only possible for an assembler written in
|
|
323
|
+
* portable C. Fasm is written in x86 assembly and has no such build.
|
|
324
|
+
*/
|
|
325
|
+
assembler?: Binary;
|
|
326
|
+
linker?: LinkerBinary;
|
|
327
|
+
};
|
|
328
|
+
/** Runs outside blink, and takes precedence over `binaries.assembler`. */
|
|
329
|
+
wasmAssembler?: WasmAssembler;
|
|
330
|
+
}
|
|
331
|
+
declare const assemblers: {
|
|
332
|
+
GNU_trunk: {
|
|
333
|
+
id: string;
|
|
334
|
+
displayName: string;
|
|
335
|
+
description: string;
|
|
336
|
+
diagnosticsParser: typeof gnuDiagnostics;
|
|
337
|
+
binaries: {
|
|
338
|
+
assembler: {
|
|
339
|
+
file: URL;
|
|
340
|
+
commands: string;
|
|
341
|
+
};
|
|
342
|
+
linker: {
|
|
343
|
+
file: URL;
|
|
344
|
+
link: (objects: readonly string[]) => string;
|
|
345
|
+
};
|
|
346
|
+
};
|
|
347
|
+
};
|
|
348
|
+
FASM_trunk: {
|
|
349
|
+
id: string;
|
|
350
|
+
displayName: string;
|
|
351
|
+
description: string;
|
|
352
|
+
diagnosticsParser: typeof fasmDiagnostics;
|
|
353
|
+
binaries: {
|
|
354
|
+
assembler: {
|
|
355
|
+
file: URL;
|
|
356
|
+
commands: string;
|
|
357
|
+
};
|
|
358
|
+
};
|
|
359
|
+
};
|
|
360
|
+
NASM_trunk: {
|
|
361
|
+
id: string;
|
|
362
|
+
displayName: string;
|
|
363
|
+
description: string;
|
|
364
|
+
diagnosticsParser: typeof nasmDiagnostics;
|
|
365
|
+
binaries: {
|
|
366
|
+
linker: {
|
|
367
|
+
file: URL;
|
|
368
|
+
link: (objects: readonly string[]) => string;
|
|
369
|
+
};
|
|
370
|
+
};
|
|
371
|
+
wasmAssembler: WasmAssembler;
|
|
372
|
+
};
|
|
373
|
+
};
|
|
374
|
+
type AssemblerId = keyof typeof assemblers;
|
|
375
|
+
declare const DEFAULT_ASSEMBLER_ID: AssemblerId;
|
|
376
|
+
declare function nasmDiagnostics(str: string): DiagnosticLine[];
|
|
377
|
+
declare function gnuDiagnostics(str: string): DiagnosticLine[];
|
|
378
|
+
declare function fasmDiagnostics(str: string): DiagnosticLine[];
|
|
379
|
+
/**
|
|
380
|
+
* What `ld` said, as diagnostics. Nothing else in the toolchain reports a symbol that no
|
|
381
|
+
* translation unit defines: NASM accepts every `extern` on the author's word, and the mistake
|
|
382
|
+
* only surfaces here. Without this the link simply failed and the build looked like it had
|
|
383
|
+
* succeeded, leaving the program unrunnable and nothing on screen to say why.
|
|
384
|
+
*
|
|
385
|
+
* `ld` writes a location as `file:line:(section+offset):`, and writes the notes that introduce an
|
|
386
|
+
* error - "in function `_start':" - as lines ending in a colon, which are skipped in favour of
|
|
387
|
+
* the error itself.
|
|
388
|
+
*/
|
|
389
|
+
declare function ldDiagnostics(str: string): DiagnosticLine[];
|
|
390
|
+
/**
|
|
391
|
+
* The one-based column a diagnostic belongs on. NASM reports a line and no
|
|
392
|
+
* column, but it names the thing it is complaining about: `msg' in "symbol
|
|
393
|
+
* `msg' not defined", `.data' in a section warning. Finding that name in the
|
|
394
|
+
* line turns a whole-line squiggle into one under the mistake itself.
|
|
395
|
+
*
|
|
396
|
+
* Falls back to the first column, which is what the caller would have used
|
|
397
|
+
* anyway, so a message that names nothing findable is no worse off.
|
|
398
|
+
*/
|
|
399
|
+
declare function locateDiagnosticColumn(message: string, line: string, warningClass?: string): number;
|
|
400
|
+
//#endregion
|
|
151
401
|
//#region src/wasm-types.d.ts
|
|
152
402
|
type EmscriptenFS = {
|
|
153
403
|
init(stdin: () => number | null, stdout: (charCode: number) => void, stderr: (charCode: number) => void): void;
|
|
@@ -291,13 +541,20 @@ declare class BlinkRuntime {
|
|
|
291
541
|
state: BlinkState;
|
|
292
542
|
stopReason: StopReason | null;
|
|
293
543
|
assemblerLogs: string;
|
|
544
|
+
/** The subset of `assemblerDiagnostics` that stopped the build. */
|
|
294
545
|
assemblerErrors: X86CompilationDiagnostic[];
|
|
546
|
+
/** Everything the assembler said, warnings included. */
|
|
547
|
+
assemblerDiagnostics: X86CompilationDiagnostic[];
|
|
295
548
|
private readonly callbacks;
|
|
296
549
|
private readonly scheduler;
|
|
297
550
|
private readonly stateWaiters;
|
|
298
551
|
private readonly stdinBytes;
|
|
299
552
|
private sourceMap;
|
|
300
553
|
private sourceProject;
|
|
554
|
+
private assembleOnly;
|
|
555
|
+
private assembledObjects;
|
|
556
|
+
/** What the linker said, kept apart from the assembler's log so `ld`'s own parser reads it. */
|
|
557
|
+
private linkerLogs;
|
|
301
558
|
private readonly defaultArgc;
|
|
302
559
|
private readonly defaultArgv;
|
|
303
560
|
private constructor();
|
|
@@ -305,6 +562,57 @@ declare class BlinkRuntime {
|
|
|
305
562
|
setMode(mode: AssemblerMode | AssemblerId): Promise<void>;
|
|
306
563
|
compileAssembly(code: string): Promise<X86CompileResult>;
|
|
307
564
|
compileProject(project: X86Project): Promise<X86CompileResult>;
|
|
565
|
+
/**
|
|
566
|
+
* Assembles without linking, for diagnostics. The linked executable is only
|
|
567
|
+
* needed to run or debug a program; a caller that just wants to know what is
|
|
568
|
+
* wrong with the source pays ~450ms for a link it never looks at.
|
|
569
|
+
*
|
|
570
|
+
* A mode with a `wasmAssembler` never touches blink here, so checking also
|
|
571
|
+
* leaves a loaded program - and anything paused in the debugger - alone.
|
|
572
|
+
*/
|
|
573
|
+
checkProject(project: X86Project): Promise<X86CompileResult>;
|
|
574
|
+
private checkProjectWithWasmAssembler;
|
|
575
|
+
private buildProject;
|
|
576
|
+
/**
|
|
577
|
+
* The objects this build's assembler wrote, for the checks that read them
|
|
578
|
+
* rather than the assembler's own words. Empty when the assembly failed, and
|
|
579
|
+
* when the assembler writes an executable directly and never produces one.
|
|
580
|
+
* Read once per build, so a previous build's objects can never stand in for
|
|
581
|
+
* ones that were never written.
|
|
582
|
+
*/
|
|
583
|
+
private takeAssembledObjects;
|
|
584
|
+
/**
|
|
585
|
+
* What the link had to say. A link that failed leaves no program to run, so a build that
|
|
586
|
+
* reported nothing would hand the caller a success it cannot act on - the state stays `Ready`
|
|
587
|
+
* and the next step or run fails with a message about the emulator rather than the mistake.
|
|
588
|
+
* The fallback covers a linker that fails in a way its parser does not recognise, so a failed
|
|
589
|
+
* link is always visible as an error whatever `ld` chose to say about it.
|
|
590
|
+
*/
|
|
591
|
+
private linkDiagnostics;
|
|
592
|
+
/**
|
|
593
|
+
* Nothing in the toolchain treats a missing entry point as a failure: NASM
|
|
594
|
+
* has no opinion on it and `ld` only warns, then starts the program at the
|
|
595
|
+
* top of its text segment, where it runs whatever happens to be first. That
|
|
596
|
+
* is the least explicable thing a program can do to someone learning, so it
|
|
597
|
+
* is reported as an error here and the mistake is usually a misspelling.
|
|
598
|
+
*/
|
|
599
|
+
private entryPointDiagnostics;
|
|
600
|
+
private assembleInBlink;
|
|
601
|
+
/**
|
|
602
|
+
* Assembles outside blink and hands the object file to the linker inside it,
|
|
603
|
+
* which is where the state machine picks up again as if blink had produced
|
|
604
|
+
* the object itself.
|
|
605
|
+
*/
|
|
606
|
+
private assembleWithWasmAssembler;
|
|
607
|
+
/**
|
|
608
|
+
* Starts the link, and starts a log of its own for it. The assembler's parser cannot read
|
|
609
|
+
* `ld`'s diagnostics and `ld`'s cannot read the assembler's, so what each of them said has to
|
|
610
|
+
* stay separable even though both reach the caller as one report.
|
|
611
|
+
*/
|
|
612
|
+
private beginLinking;
|
|
613
|
+
private collectAssemblerDiagnostics;
|
|
614
|
+
private emitAssemblerOutput;
|
|
615
|
+
private parseAssemblerDiagnostics;
|
|
308
616
|
loadElf(data: ArrayBuffer | Uint8Array): void;
|
|
309
617
|
starti(): void;
|
|
310
618
|
pauseAtEntry(): void;
|
|
@@ -355,170 +663,6 @@ declare class BlinkRuntime {
|
|
|
355
663
|
private tryReadSourceMap;
|
|
356
664
|
}
|
|
357
665
|
//#endregion
|
|
358
|
-
//#region src/interface.d.ts
|
|
359
|
-
type StatusRegister = {
|
|
360
|
-
name: string;
|
|
361
|
-
value: number;
|
|
362
|
-
prev: number;
|
|
363
|
-
};
|
|
364
|
-
type MonacoError = {
|
|
365
|
-
/** Project-relative source path when checking a virtual Project. */file?: string;
|
|
366
|
-
lineIndex: number;
|
|
367
|
-
column: number;
|
|
368
|
-
line: {
|
|
369
|
-
line: string;
|
|
370
|
-
line_index: number;
|
|
371
|
-
};
|
|
372
|
-
message: string;
|
|
373
|
-
formatted: string;
|
|
374
|
-
};
|
|
375
|
-
type StackFrame = {
|
|
376
|
-
name: string;
|
|
377
|
-
address: bigint;
|
|
378
|
-
destination: bigint;
|
|
379
|
-
sp: bigint;
|
|
380
|
-
line: number;
|
|
381
|
-
file?: string;
|
|
382
|
-
color: string;
|
|
383
|
-
};
|
|
384
|
-
type RegisterHex = [hi: string, lo: string];
|
|
385
|
-
declare enum RegisterSize {
|
|
386
|
-
Byte = 1,
|
|
387
|
-
Word = 2,
|
|
388
|
-
Long = 4,
|
|
389
|
-
Double = 8
|
|
390
|
-
}
|
|
391
|
-
type ExecutionStep = {
|
|
392
|
-
mutations: MutationOperation[];
|
|
393
|
-
pc: number;
|
|
394
|
-
old_ccr: {
|
|
395
|
-
bits: number;
|
|
396
|
-
};
|
|
397
|
-
new_ccr: {
|
|
398
|
-
bits: number;
|
|
399
|
-
};
|
|
400
|
-
line: number;
|
|
401
|
-
file?: string;
|
|
402
|
-
};
|
|
403
|
-
type MutationOperation = {
|
|
404
|
-
type: 'WriteRegister';
|
|
405
|
-
value: {
|
|
406
|
-
register: string;
|
|
407
|
-
old: bigint;
|
|
408
|
-
size: RegisterSize;
|
|
409
|
-
};
|
|
410
|
-
} | {
|
|
411
|
-
type: 'WriteMemory';
|
|
412
|
-
value: {
|
|
413
|
-
address: bigint;
|
|
414
|
-
old: bigint;
|
|
415
|
-
size: RegisterSize;
|
|
416
|
-
};
|
|
417
|
-
} | {
|
|
418
|
-
type: 'WriteMemoryBytes';
|
|
419
|
-
value: {
|
|
420
|
-
address: bigint;
|
|
421
|
-
old: number[];
|
|
422
|
-
};
|
|
423
|
-
} | {
|
|
424
|
-
type: 'PopCallStack';
|
|
425
|
-
value: {
|
|
426
|
-
to: bigint;
|
|
427
|
-
from: bigint;
|
|
428
|
-
};
|
|
429
|
-
} | {
|
|
430
|
-
type: 'PushCallStack';
|
|
431
|
-
value: {
|
|
432
|
-
to: bigint;
|
|
433
|
-
from: bigint;
|
|
434
|
-
};
|
|
435
|
-
} | {
|
|
436
|
-
type: 'Other';
|
|
437
|
-
value: string;
|
|
438
|
-
};
|
|
439
|
-
type EmulatorDecoration = {
|
|
440
|
-
type: 'below-line';
|
|
441
|
-
note?: string;
|
|
442
|
-
belowLine: number;
|
|
443
|
-
md: string;
|
|
444
|
-
};
|
|
445
|
-
type CompilationError = {
|
|
446
|
-
type: 'raw';
|
|
447
|
-
message: string;
|
|
448
|
-
};
|
|
449
|
-
declare enum EmulatorStatus {
|
|
450
|
-
Terminated = 0,
|
|
451
|
-
Running = 1,
|
|
452
|
-
WaitingForInput = 2,
|
|
453
|
-
NotReady = 3
|
|
454
|
-
}
|
|
455
|
-
type Instruction = {
|
|
456
|
-
address: bigint;
|
|
457
|
-
lineNumber: number;
|
|
458
|
-
file?: string;
|
|
459
|
-
size?: number;
|
|
460
|
-
bytes?: Uint8Array;
|
|
461
|
-
code: string;
|
|
462
|
-
};
|
|
463
|
-
type EmulatorConfig<R extends string> = {
|
|
464
|
-
systemSize: RegisterSize;
|
|
465
|
-
registerNames: R[];
|
|
466
|
-
endianness?: 'little' | 'big';
|
|
467
|
-
hiddenRegisters?: R[];
|
|
468
|
-
};
|
|
469
|
-
declare abstract class BaseEmulator<T, R extends string, CompileResult = {
|
|
470
|
-
ok: true;
|
|
471
|
-
} | {
|
|
472
|
-
ok: false;
|
|
473
|
-
errors: CompilationError[];
|
|
474
|
-
report: string;
|
|
475
|
-
}> {
|
|
476
|
-
protected _registerNames: R[];
|
|
477
|
-
protected _systemSize: RegisterSize;
|
|
478
|
-
protected _endianness: 'little' | 'big';
|
|
479
|
-
constructor(options: EmulatorConfig<R>);
|
|
480
|
-
getSystemSize(): RegisterSize;
|
|
481
|
-
getEndianness(): 'little' | 'big';
|
|
482
|
-
getRegisterNames(): R[];
|
|
483
|
-
abstract initialize(undoSize: number): void;
|
|
484
|
-
abstract getCompiledCode(): {
|
|
485
|
-
decorations: EmulatorDecoration[];
|
|
486
|
-
code: string;
|
|
487
|
-
};
|
|
488
|
-
abstract dispose(): void;
|
|
489
|
-
abstract stringifyError(error: unknown): string;
|
|
490
|
-
abstract compile(code: string): Promise<CompileResult>;
|
|
491
|
-
abstract checkCode(code: string): Promise<MonacoError[]>;
|
|
492
|
-
abstract undo(): void;
|
|
493
|
-
abstract canUndo(): boolean;
|
|
494
|
-
abstract step(): Promise<{
|
|
495
|
-
terminated: boolean;
|
|
496
|
-
}>;
|
|
497
|
-
abstract getStatus(): EmulatorStatus;
|
|
498
|
-
abstract writeMemoryBytes(address: bigint, data: Uint8Array): void;
|
|
499
|
-
abstract readMemoryBytes(address: bigint, length: bigint): Uint8Array;
|
|
500
|
-
abstract getNextInstruction(): Instruction | null;
|
|
501
|
-
abstract getUndoHistory(max: number): ExecutionStep[];
|
|
502
|
-
abstract getPc(): bigint;
|
|
503
|
-
abstract getSp(): bigint;
|
|
504
|
-
abstract getFlags(): {
|
|
505
|
-
name: string;
|
|
506
|
-
value: number;
|
|
507
|
-
prev?: number;
|
|
508
|
-
}[];
|
|
509
|
-
abstract getCallStack(): StackFrame[];
|
|
510
|
-
abstract getInstructionAt(address: bigint): Instruction | null;
|
|
511
|
-
abstract getRegisterValues(): bigint[];
|
|
512
|
-
abstract getRegisterValuesRecord(): Record<R, bigint>;
|
|
513
|
-
abstract getRegisterValue(register: R, size?: RegisterSize): bigint;
|
|
514
|
-
abstract setRegisterValue(register: R, value: bigint, size?: RegisterSize): void;
|
|
515
|
-
abstract hasTerminated(): boolean;
|
|
516
|
-
abstract run(limit?: number, breakpoints?: Array<number | {
|
|
517
|
-
path: string;
|
|
518
|
-
line: number;
|
|
519
|
-
}>): Promise<EmulatorStatus>;
|
|
520
|
-
}
|
|
521
|
-
//#endregion
|
|
522
666
|
//#region src/project.d.ts
|
|
523
667
|
declare const X86_PROJECT_ROOT = "/__x86_project";
|
|
524
668
|
declare function validateX86Project(project: X86Project): void;
|
|
@@ -528,6 +672,13 @@ declare function validateX86Project(project: X86Project): void;
|
|
|
528
672
|
* preprocessor macros.
|
|
529
673
|
*/
|
|
530
674
|
declare function stageX86Project(fs: EmscriptenFS, project: X86Project): void;
|
|
675
|
+
/**
|
|
676
|
+
* Points the assembler at one staged Project File and leaves that File's own directory as the
|
|
677
|
+
* working directory, so its `%include`s and `incbin`s resolve from where it was written rather
|
|
678
|
+
* than from wherever the Entry happens to live. The Entry keeps its `/assembly.s` identity, which
|
|
679
|
+
* is the path its existing diagnostics and source maps are written in terms of.
|
|
680
|
+
*/
|
|
681
|
+
declare function selectX86Source(fs: EmscriptenFS, project: X86Project, path: string): string;
|
|
531
682
|
/** Maps a path emitted by NASM or DWARF back to the exact Project path. */
|
|
532
683
|
declare function x86ProjectSourcePath(sourcePath: string | undefined, project: Pick<X86Project, 'entry' | 'files'>): string;
|
|
533
684
|
declare function x86ProjectText(project: X86Project, path: string): string;
|
|
@@ -564,6 +715,11 @@ declare class X86Emulator extends BaseEmulator<BlinkRuntime, X86RegisterName, X8
|
|
|
564
715
|
dispose(): void;
|
|
565
716
|
stringifyError(error: unknown): string;
|
|
566
717
|
checkCode(code: string): Promise<MonacoError[]>;
|
|
718
|
+
/**
|
|
719
|
+
* Diagnostics only: this assembles but does not link, and for an assembler
|
|
720
|
+
* that runs as its own wasm module it does not touch blink at all, so a
|
|
721
|
+
* loaded or paused program survives a check.
|
|
722
|
+
*/
|
|
567
723
|
checkProject(project: X86Project): Promise<MonacoError[]>;
|
|
568
724
|
undo(): void;
|
|
569
725
|
canUndo(): boolean;
|
|
@@ -607,5 +763,5 @@ declare class X86Emulator extends BaseEmulator<BlinkRuntime, X86RegisterName, X8
|
|
|
607
763
|
}
|
|
608
764
|
declare function createX86Emulator(options?: X86EmulatorOptions): Promise<X86Emulator>;
|
|
609
765
|
//#endregion
|
|
610
|
-
export { AssemblerId, AssemblerMode, BaseEmulator, Binary, BlinkRunOptions, BlinkRuntime, BlinkRuntimeCallbacks, BlinkRuntimeOptions, BlinkState, BlinkenlibModule, BlinkenlibModuleOptions, CompilationError, DEFAULT_ASSEMBLER_ID, DiagnosticLine, DiagnosticsParser, DisassemblySnapshot, EmscriptenFS, EmulatorConfig, EmulatorDecoration, EmulatorStatus, ExecutionStep, Instruction, MaybePromise, MemoryReadResult, MemoryWriteResult, MonacoError, MutationOperation, NativeControlFlowKind, NativeInstruction, NativeMemoryWrite, NativeRunControls, NativeRunStop, NativeRunStopKind, NativeStepInfo, NativeSymbol, RegisterHex, RegisterSize, RegisterSnapshot, ResourceSource, StackFrame, StatusRegister, StopReason, StopReasonKind, X86Breakpoint, X86CompilationDiagnostic, X86CompileResult, X86Emulator, X86EmulatorEventHandler, X86EmulatorEventMap, X86EmulatorEventName, X86EmulatorOptions, X86Project, X86ProjectFile, X86RegisterName, X86SourceLocation, X86_PROJECT_ROOT, X86_REGISTER_NAMES, assemblers, createX86Emulator, defaultResourceUrl, fasmDiagnostics, gnuDiagnostics, isNodeRuntime, nasmDiagnostics, observeCallbackResult, readResourceBytes, stageX86Project, toResourceUrl, validateX86Project, x86ProjectSourcePath, x86ProjectText };
|
|
766
|
+
export { AssemblerId, AssemblerMode, BaseEmulator, Binary, BlinkRunOptions, BlinkRuntime, BlinkRuntimeCallbacks, BlinkRuntimeOptions, BlinkState, BlinkenlibModule, BlinkenlibModuleOptions, CompilationError, DEFAULT_ASSEMBLER_ID, DiagnosticLine, DiagnosticSeverity, DiagnosticsParser, DisassemblySnapshot, EmscriptenFS, EmulatorConfig, EmulatorDecoration, EmulatorStatus, ExecutionStep, Instruction, LinkerBinary, MaybePromise, MemoryReadResult, MemoryWriteResult, MonacoError, MutationOperation, NativeControlFlowKind, NativeInstruction, NativeMemoryWrite, NativeRunControls, NativeRunStop, NativeRunStopKind, NativeStepInfo, NativeSymbol, RegisterHex, RegisterSize, RegisterSnapshot, ResourceSource, StackFrame, StatusRegister, StopReason, StopReasonKind, X86Breakpoint, X86CompilationDiagnostic, X86CompileResult, X86Emulator, X86EmulatorEventHandler, X86EmulatorEventMap, X86EmulatorEventName, X86EmulatorOptions, X86Project, X86ProjectFile, X86RegisterName, X86SourceLocation, X86_PROJECT_ROOT, X86_REGISTER_NAMES, assemblers, createX86Emulator, defaultResourceUrl, fasmDiagnostics, gnuDiagnostics, isNodeRuntime, ldDiagnostics, locateDiagnosticColumn, nasmDiagnostics, observeCallbackResult, readResourceBytes, selectX86Source, stageX86Project, toResourceUrl, validateX86Project, x86ProjectSourcePath, x86ProjectText };
|
|
611
767
|
//# sourceMappingURL=index.d.mts.map
|