@scriptc/compiler 0.3.3 → 0.3.4
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/ambient/scriptc-node-fallback.d.ts +713 -26
- package/dist/backend/cycle-mutability.d.ts +5 -0
- package/dist/backend/cycle-mutability.js +62 -3
- package/dist/backend/cycle-mutability.js.map +1 -1
- package/dist/backend/executable-features.js +1 -0
- package/dist/backend/executable-features.js.map +1 -1
- package/dist/backend/library-pack.js +1 -0
- package/dist/backend/library-pack.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.d.ts +5 -1
- package/dist/backend/llvm/call-lifetimes.js +11 -3
- package/dist/backend/llvm/call-lifetimes.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.test.js +31 -1
- package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +5 -0
- package/dist/backend/llvm/common.js +7 -0
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/dense-array-access.js +2 -2
- package/dist/backend/llvm/dense-array-access.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +40 -1
- package/dist/backend/llvm/dyn.js +178 -27
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +12 -0
- package/dist/backend/llvm/emitter.js +164 -27
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +9 -0
- package/dist/backend/llvm/expr-bytes.js +158 -63
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-calls.d.ts +3 -1
- package/dist/backend/llvm/expr-calls.js +49 -1
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.js +16 -5
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/intern-tables.test.d.ts +1 -0
- package/dist/backend/llvm/intern-tables.test.js +77 -0
- package/dist/backend/llvm/intern-tables.test.js.map +1 -0
- package/dist/backend/llvm/lib-datagram.js +10 -0
- package/dist/backend/llvm/lib-datagram.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +92 -1
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +51 -0
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-network.js +16 -0
- package/dist/backend/llvm/lib-network.js.map +1 -1
- package/dist/backend/llvm/lib-shared.d.ts +5 -0
- package/dist/backend/llvm/lib-shared.js +80 -1
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +87 -0
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/lib-test.js +9 -0
- package/dist/backend/llvm/lib-test.js.map +1 -1
- package/dist/backend/llvm/map-number-lookup.d.ts +4 -0
- package/dist/backend/llvm/map-number-lookup.js +22 -0
- package/dist/backend/llvm/map-number-lookup.js.map +1 -1
- package/dist/backend/llvm/map-number-lookup.test.js +56 -0
- package/dist/backend/llvm/map-number-lookup.test.js.map +1 -1
- package/dist/backend/llvm/map-read-lifetimes.d.ts +9 -0
- package/dist/backend/llvm/map-read-lifetimes.js +89 -1
- package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
- package/dist/backend/llvm/map-read-lifetimes.test.js +129 -1
- package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/publish.d.ts +5 -0
- package/dist/backend/llvm/publish.js +22 -3
- package/dist/backend/llvm/publish.js.map +1 -1
- package/dist/backend/llvm/reference-writes.js +5 -2
- package/dist/backend/llvm/reference-writes.js.map +1 -1
- package/dist/backend/llvm/regions.d.ts +4 -1
- package/dist/backend/llvm/regions.js +12 -3
- package/dist/backend/llvm/regions.js.map +1 -1
- package/dist/backend/llvm/string-reads.js +2 -2
- package/dist/backend/llvm/string-reads.js.map +1 -1
- package/dist/backend/llvm/string-slices.js +2 -2
- package/dist/backend/llvm/string-slices.js.map +1 -1
- package/dist/backend/may-throw.js +4 -0
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/native/contracts.d.ts +3 -0
- package/dist/backend/native/executable.js +13 -5
- package/dist/backend/native/executable.js.map +1 -1
- package/dist/backend/native/runtime-inputs.d.ts +1 -1
- package/dist/backend/native/runtime-inputs.js +1 -0
- package/dist/backend/native/runtime-inputs.js.map +1 -1
- package/dist/backend/native-codegen-core.d.ts +4 -4
- package/dist/backend/native-codegen-core.js +4 -6
- package/dist/backend/native-codegen-core.js.map +1 -1
- package/dist/backend/native-codegen.test.js +7 -8
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +3 -0
- package/dist/backend/native-link-info-core.js.map +1 -1
- package/dist/backend/publication.js +3 -1
- package/dist/backend/publication.js.map +1 -1
- package/dist/backend/runtime-pack-targets.test.js +1 -0
- package/dist/backend/runtime-pack-targets.test.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +1 -0
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/target-diagnostics.js +7 -0
- package/dist/backend/target-diagnostics.js.map +1 -1
- package/dist/backend/warm-cache.js +1 -0
- package/dist/backend/warm-cache.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +1 -0
- package/dist/executable/executable-cache.js +1 -0
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +1 -0
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/frontend/experimental-import.d.ts +5 -1
- package/dist/frontend/experimental-import.js +28 -3
- package/dist/frontend/experimental-import.js.map +1 -1
- package/dist/frontend/lowering/assert-instances.d.ts +38 -0
- package/dist/frontend/lowering/assert-instances.js +269 -0
- package/dist/frontend/lowering/assert-instances.js.map +1 -0
- package/dist/frontend/lowering/builtins/compression.d.ts +18 -0
- package/dist/frontend/lowering/builtins/compression.js +175 -2
- package/dist/frontend/lowering/builtins/compression.js.map +1 -1
- package/dist/frontend/lowering/builtins/constants.js +7 -2
- package/dist/frontend/lowering/builtins/constants.js.map +1 -1
- package/dist/frontend/lowering/builtins/crypto.d.ts +6 -0
- package/dist/frontend/lowering/builtins/crypto.js +111 -1
- package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
- package/dist/frontend/lowering/builtins/errors.js +23 -0
- package/dist/frontend/lowering/builtins/errors.js.map +1 -1
- package/dist/frontend/lowering/builtins/timers.d.ts +3 -0
- package/dist/frontend/lowering/builtins/timers.js +109 -23
- package/dist/frontend/lowering/builtins/timers.js.map +1 -1
- package/dist/frontend/lowering/call-signatures.js +6 -0
- package/dist/frontend/lowering/call-signatures.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.js +66 -12
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/intern-tables.d.ts +13 -0
- package/dist/frontend/lowering/intern-tables.js +536 -0
- package/dist/frontend/lowering/intern-tables.js.map +1 -0
- package/dist/frontend/lowering/lower-assert.js +700 -61
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-async-iteration.js +11 -2
- package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +17 -3
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +3 -0
- package/dist/frontend/lowering/lower-classes.js +36 -0
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.js +77 -52
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.js +12 -0
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.d.ts +6 -0
- package/dist/frontend/lowering/lower-inspect.js +112 -39
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-mock.d.ts +11 -0
- package/dist/frontend/lowering/lower-mock.js +504 -0
- package/dist/frontend/lowering/lower-mock.js.map +1 -0
- package/dist/frontend/lowering/lower-modules.js +7 -0
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +3 -0
- package/dist/frontend/lowering/lower-server.js +380 -30
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +23 -2
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +10 -6
- package/dist/frontend/lowering/lower-stream.js +786 -27
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-test.js +86 -8
- package/dist/frontend/lowering/lower-test.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +22 -0
- package/dist/frontend/lowering/lowerer.js +72 -7
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/pairs-snapshot.d.ts +6 -0
- package/dist/frontend/lowering/pairs-snapshot.js +49 -0
- package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +4 -0
- package/dist/frontend/lowering/surfaces.js +61 -15
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/zlib-constants.d.ts +1 -0
- package/dist/frontend/lowering/zlib-constants.js +181 -0
- package/dist/frontend/lowering/zlib-constants.js.map +1 -0
- package/dist/frontend/mock-shapes.d.ts +10 -0
- package/dist/frontend/mock-shapes.js +76 -0
- package/dist/frontend/mock-shapes.js.map +1 -0
- package/dist/frontend/pipeline.js +5 -3
- package/dist/frontend/pipeline.js.map +1 -1
- package/dist/frontend/program.js +6 -1
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/resolve.d.ts +4 -0
- package/dist/frontend/resolve.js +14 -0
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/tsc-codes.js +1 -0
- package/dist/frontend/tsc-codes.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +5 -0
- package/dist/frontend/type-mapper.js +102 -9
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/ir/builtin-effects.js +36 -0
- package/dist/ir/builtin-effects.js.map +1 -1
- package/dist/ir/builtin-signatures.d.ts +1 -1
- package/dist/ir/builtin-signatures.js +147 -8
- package/dist/ir/builtin-signatures.js.map +1 -1
- package/dist/ir/ir.d.ts +20 -1
- package/dist/ir/ir.js +17 -0
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/runtime-features.d.ts +1 -0
- package/dist/ir/runtime-features.js +29 -2
- package/dist/ir/runtime-features.js.map +1 -1
- package/dist/ir/validate.js +195 -5
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/ir-policy.js +1 -0
- package/dist/library/ir-policy.js.map +1 -1
- package/dist/native/cli.js +1 -0
- package/dist/native/cli.js.map +1 -1
- package/dist/native/compiler.js +1 -3
- package/dist/native/compiler.js.map +1 -1
- package/dist/native/prepare.js +1 -0
- package/dist/native/prepare.js.map +1 -1
- package/dist/native/sanitizer.test.js +1 -0
- package/dist/native/sanitizer.test.js.map +1 -1
- package/package.json +20 -20
- package/surface-manifest.json +869 -48
|
@@ -215,6 +215,7 @@ export declare class LlEmitter {
|
|
|
215
215
|
readonly checkedNarrows: CheckedNarrows;
|
|
216
216
|
callArrayReads: Map<IrExpr, LocalArrayRead>;
|
|
217
217
|
mapReadLifetimes: MapReadLifetimes;
|
|
218
|
+
readNumberMapWrites: ReadonlySet<IrExpr>;
|
|
218
219
|
readonly callLifetimes: CallLifetimes;
|
|
219
220
|
readonly constantCallbacks: Map<string, Map<string, string>>;
|
|
220
221
|
currentConstantCallbacks: ReadonlyMap<string, string>;
|
|
@@ -687,6 +688,11 @@ export declare class LlEmitter {
|
|
|
687
688
|
* conditions in expr-calls.ts). */
|
|
688
689
|
private callTestsPending;
|
|
689
690
|
private workerLoopBudget;
|
|
691
|
+
/** The amortized cancellation poll, emitted on the loop's back edge (the
|
|
692
|
+
* continue target), after the body. A poll in the header would be a loop
|
|
693
|
+
* exit ahead of the body; LLVM then cannot rotate the loop, so loads that
|
|
694
|
+
* the body repeats on every iteration (a typed array's length, for one)
|
|
695
|
+
* stay in the loop. */
|
|
690
696
|
private emitWorkerLoopCheck;
|
|
691
697
|
/** Moves an already-evaluated value into the runtime's exception cell —
|
|
692
698
|
* the `throw` statement's kind dispatch (stmts.ts's), shared with
|
|
@@ -1036,6 +1042,12 @@ export declare class LlEmitter {
|
|
|
1036
1042
|
emitRecordExpr(e: ExprOf<"fieldGet" | "recordGet" | "recordLit" | "recordClone" | "recordKeyGet" | "recordOvfKeys" | "recordOvfHas" | "recordHas" | "fieldAbsent">): LlValue;
|
|
1037
1043
|
emitDynamicExpr(e: ExprOf<"dynFrom" | "dynCall" | "dynInvoke" | "dynArrLit" | "dynObjLit" | "unionWrap" | "unionNarrow" | "unionDisc" | "unionKeyGet" | "unionIsTag" | "dynKeyGet" | "dynHasKey" | "dynScalarEq" | "dynTest" | "unionEq" | "unionFuncEq" | "caughtTest" | "caughtCheck" | "caughtNarrow" | "caughtToDyn">): LlValue;
|
|
1038
1044
|
emitIntrinsicExpr(e: ExprOf<"intrinsic">): LlValue;
|
|
1045
|
+
/** InternTable's runtime calls (scr_itable.c). Table and entry handles
|
|
1046
|
+
* are f64 values carrying pointer bits; entry values are 64-bit slots
|
|
1047
|
+
* (double bits, a bool, or a pointer to an immortal value) that the
|
|
1048
|
+
* table neither retains nor releases. Lookups and inserts of array keys
|
|
1049
|
+
* throw a TypeError for keys longer than a table accepts. */
|
|
1050
|
+
private emitInternTableIntrinsic;
|
|
1039
1051
|
/** Lifetime regions in modules with lifetimeRegions (llvm/regions.ts).
|
|
1040
1052
|
* Created with the class graph; null elsewhere. */
|
|
1041
1053
|
private regions;
|
|
@@ -46,9 +46,9 @@ import { InlineUnionFields, loadInlineUnion, presentBits, stackUnionBox, storeIn
|
|
|
46
46
|
import { emitLocalArrayRead, emitProjectedArrayRead, emitBorrowedArrayRead, findLocalArrayReads, findCallArrayReads, OptionalArrayReads, } from "./local-array-reads.js";
|
|
47
47
|
import { CheckedNarrows, emitCheckedNarrowReceiver } from "./checked-narrows.js";
|
|
48
48
|
import { emitDenseArrayGet, emitDenseArraySet } from "./dense-array-access.js";
|
|
49
|
-
import { emitStackMapRead, findMapReadLifetimes, matchMapRead, } from "./map-read-lifetimes.js";
|
|
49
|
+
import { emitStackMapRead, findMapReadLifetimes, findReadNumberMapWrites, matchMapRead, } from "./map-read-lifetimes.js";
|
|
50
50
|
import { emitBorrowedFieldSequence, guardedValue } from "./borrowed-receivers.js";
|
|
51
|
-
import { borrowableInputs, emitBorrowedInput } from "./borrowed-inputs.js";
|
|
51
|
+
import { borrowableInputs, emitBorrowedInput, emitBorrowedInputs } from "./borrowed-inputs.js";
|
|
52
52
|
import { analyzeWalks, findWalkBorrows } from "./walk-borrows.js";
|
|
53
53
|
import { findReboundParameters } from "./rebound-parameters.js";
|
|
54
54
|
import { ReferenceEffects } from "./reference-effects.js";
|
|
@@ -61,7 +61,7 @@ import { AmbientReceiverReaders, findConstantCallbacks } from "./constant-callba
|
|
|
61
61
|
import { findScalarStringSlices, emitStringSliceSnapshot, } from "./string-slices.js";
|
|
62
62
|
import { LazyCaptures } from "./lazy-captures.js";
|
|
63
63
|
import { StackCaptures } from "./stack-captures.js";
|
|
64
|
-
import { ABSENT_FIELD_PAYLOAD, emitFieldAbsentTest, exactIndexLines, f64Lit, ffiNativeTypeLl, ffiNativeParamLl, ffiNativeReturnLl, llvmCommentText, } from "./common.js";
|
|
64
|
+
import { ABSENT_FIELD_PAYLOAD, emitFieldAbsentTest, exactIndexLines, f64Lit, ffiNativeTypeLl, ffiNativeParamLl, ffiNativeReturnLl, llvmCommentText, sizeToDouble, } from "./common.js";
|
|
65
65
|
import { ffiExtendsNarrowIntegers } from "../targets.js";
|
|
66
66
|
import { emitLiteralExpr, emitOperatorExpr, emitStringExpr, emitContainerExpr, emitRecordExpr, } from "./expr-primitives.js";
|
|
67
67
|
import { emitControlExpr } from "./expr-control.js";
|
|
@@ -85,7 +85,7 @@ import { emitNetworkHttpLibCall } from "./lib-network.js";
|
|
|
85
85
|
import { emitAssertInspectLibCall, emitIoLibCall, emitGenericLibCall, emitLibCall, } from "./lib-dispatch.js";
|
|
86
86
|
import { buildClassGraph, classMembershipIntervals, emitClassMembershipHelper, classEnvironmentIndex, classFieldIndex, classStructSym, programLifetimeClass, } from "./classes.js";
|
|
87
87
|
import { LifetimeRegions, REGION_TYPES } from "./regions.js";
|
|
88
|
-
import { LlDyn } from "./dyn.js";
|
|
88
|
+
import { LlDyn, recordDynKeepsIdentity } from "./dyn.js";
|
|
89
89
|
import { VirtualBorrows } from "./virtual-borrows.js";
|
|
90
90
|
import { LlvmUnsupportedError } from "./unsupported.js";
|
|
91
91
|
import { LlWalkers } from "./walkers.js";
|
|
@@ -354,6 +354,7 @@ export class LlEmitter {
|
|
|
354
354
|
checkedNarrows;
|
|
355
355
|
callArrayReads = new Map();
|
|
356
356
|
mapReadLifetimes = { locals: new Map(), arguments: new Map() };
|
|
357
|
+
readNumberMapWrites = new Set();
|
|
357
358
|
callLifetimes;
|
|
358
359
|
constantCallbacks;
|
|
359
360
|
currentConstantCallbacks = new Map();
|
|
@@ -737,6 +738,9 @@ export class LlEmitter {
|
|
|
737
738
|
this.callLifetimes = analyzeCallLifetimes(this.fnByName, (className, field) => this.nullableFields.get(className, field) !== null, walkParameters, new Set([...this.int32Abis].filter(([, abi]) => abi.union).map(([name]) => name)), {
|
|
738
739
|
record: (shapeId, field) => this.recordFieldInline(shapeId, field),
|
|
739
740
|
classField: (className, field) => this.inlineUnions.classField(className, field),
|
|
741
|
+
}, (shapeId) => {
|
|
742
|
+
const shape = this.recordsById.get(shapeId);
|
|
743
|
+
return shape !== undefined && !recordDynKeepsIdentity(shape);
|
|
740
744
|
});
|
|
741
745
|
this.constantCallbacks = findConstantCallbacks(mod, this.callLifetimes);
|
|
742
746
|
this.stackCallbacks = new StackCallbacks(this.fnByName);
|
|
@@ -1413,21 +1417,17 @@ export class LlEmitter {
|
|
|
1413
1417
|
if (!asyncEntry)
|
|
1414
1418
|
return [];
|
|
1415
1419
|
const lines = [];
|
|
1420
|
+
// finish_top_level noted 13 unless the program set process.exitCode.
|
|
1421
|
+
// A failed node:test run outranks either before exit listeners run.
|
|
1416
1422
|
if (usesNodeTest) {
|
|
1417
|
-
lines.push(` %tla_program_exit = call i32 @scr_test_exit_code()`);
|
|
1423
|
+
lines.push(` %tla_program_exit = call i32 @scr_test_exit_code()`, ` %tla_program_exit_zero = icmp eq i32 %tla_program_exit, 0`, ` %tla_hint = call i32 @scr_exit_code_hint_get()`, ` %tla_exit_status = select i1 %tla_program_exit_zero, i32 %tla_hint, i32 %tla_program_exit`, ` call void @scr_exit_code_note(i32 %tla_exit_status)`);
|
|
1418
1424
|
}
|
|
1419
|
-
if (usesNodeTest) {
|
|
1420
|
-
lines.push(` %tla_program_exit_zero = icmp eq i32 %tla_program_exit, 0`, ` %tla_exit_status = select i1 %tla_program_exit_zero, i32 %tla_status, i32 %tla_program_exit`);
|
|
1421
|
-
}
|
|
1422
|
-
const exitStatus = usesNodeTest ? "%tla_exit_status" : "%tla_status";
|
|
1423
|
-
// finish_top_level initially notes 13. Replace that hint before exit
|
|
1424
|
-
// listeners run when a higher-priority verdict was already selected.
|
|
1425
|
-
lines.push(` call void @scr_exit_code_note(i32 ${exitStatus})`);
|
|
1426
1425
|
for (const line of exitListenerLines("xp"))
|
|
1427
1426
|
lines.push(line);
|
|
1428
1427
|
for (const line of topPendingReleases)
|
|
1429
1428
|
lines.push(line);
|
|
1430
|
-
|
|
1429
|
+
// An exit listener may set process.exitCode again, as in Node.
|
|
1430
|
+
lines.push(` %tla_exit_code = call i32 @scr_exit_code_hint_get()`, ` ret i32 %tla_exit_code`);
|
|
1431
1431
|
return lines;
|
|
1432
1432
|
};
|
|
1433
1433
|
// LIBRARY mode: the runtime entry points the generated library
|
|
@@ -2185,9 +2185,13 @@ export class LlEmitter {
|
|
|
2185
2185
|
// Number-key Map/Set lookups probe the runtime's direct index inline:
|
|
2186
2186
|
// while ndense is nonzero every live key is an integer below it, so an
|
|
2187
2187
|
// in-range integral key reads its slot (entry index + 1, 0 = absent) and
|
|
2188
|
-
// any other key is absent. Maps without the index (ndense 0)
|
|
2189
|
-
//
|
|
2190
|
-
//
|
|
2188
|
+
// any other key is absent. Maps without the index (ndense 0) hash the
|
|
2189
|
+
// key in sc_map_entry_f64_hashed, which scans the entries of a small map
|
|
2190
|
+
// or probes a compact bucket table as scr_map_find_f64 does, and calls
|
|
2191
|
+
// the runtime lookup for a wide table. It stays out of line so that the
|
|
2192
|
+
// direct-index path stays small at every call site. Both only read
|
|
2193
|
+
// memory, so LLVM merges lookups of one key when nothing is stored in
|
|
2194
|
+
// between (a has() followed by get(), for example).
|
|
2191
2195
|
if (this.decls.has(NUMBER_MAP_ENTRY_DECL)) {
|
|
2192
2196
|
const sz = this.sizeType;
|
|
2193
2197
|
let mapTmp = 0;
|
|
@@ -2196,7 +2200,15 @@ export class LlEmitter {
|
|
|
2196
2200
|
// A non-integral key inside the table is as absent as one outside it.
|
|
2197
2201
|
...mapIndex.lines.map((line) => ` ${line}`), ` br i1 ${mapIndex.ok}, label %slot, label %outside`, `slot:`, sz === "i64"
|
|
2198
2202
|
? ` %i = add i64 ${mapIndex.wide}, 0`
|
|
2199
|
-
: ` %i = trunc i64 ${mapIndex.wide} to ${sz}`, ` %dp = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 19`, ` %dense = load ptr, ptr %dp`, ` %sp = getelementptr inbounds i32, ptr %dense, ${sz} %i`, ` %s = load i32, ptr %sp`, ` %empty = icmp eq i32 %s, 0`, ` br i1 %empty, label %miss, label %hit`, `hit:`, ` %e32 = sub i32 %s, 1`, sz === "i32" ? ` %e = add i32 %e32, 0` : ` %e = zext i32 %e32 to ${sz}`, ` %ep = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 13`, ` %entries = load ptr, ptr %ep`, ` %found = getelementptr inbounds %ScrMapEntry, ptr %entries, ${sz} %e`, ` ret ptr %found`, `miss:`, ` ret ptr null`, `outside:`, ` %dense.any = icmp ne ${sz} %nd, 0`, ` br i1 %dense.any, label %miss, label %slow`, `slow:`, ` %
|
|
2203
|
+
: ` %i = trunc i64 ${mapIndex.wide} to ${sz}`, ` %dp = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 19`, ` %dense = load ptr, ptr %dp`, ` %sp = getelementptr inbounds i32, ptr %dense, ${sz} %i`, ` %s = load i32, ptr %sp`, ` %empty = icmp eq i32 %s, 0`, ` br i1 %empty, label %miss, label %hit`, `hit:`, ` %e32 = sub i32 %s, 1`, sz === "i32" ? ` %e = add i32 %e32, 0` : ` %e = zext i32 %e32 to ${sz}`, ` %ep = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 13`, ` %entries = load ptr, ptr %ep`, ` %found = getelementptr inbounds %ScrMapEntry, ptr %entries, ${sz} %e`, ` ret ptr %found`, `miss:`, ` ret ptr null`, `outside:`, ` %dense.any = icmp ne ${sz} %nd, 0`, ` br i1 %dense.any, label %miss, label %slow`, `slow:`, ` %hashed = call ptr @sc_map_entry_f64_hashed(ptr %m, double %k)`, ` ret ptr %hashed`, `}`, ``,
|
|
2204
|
+
// Hashing (scr_map_find_f64): the SameValueZero key word, its
|
|
2205
|
+
// scr_key_mix hash (zero remapped to one) and the absent-key filter.
|
|
2206
|
+
`define internal ptr @sc_map_entry_f64_hashed(ptr %m, double %k) noinline ${FN_ATTRS} {`, `entry:`, ` %nan = fcmp uno double %k, %k`, ` %zero = fcmp oeq double %k, 0.0`, ` %kz = select i1 %zero, double 0.0, double %k`, ` %kzb = bitcast double %kz to i64`, ` %kb = select i1 %nan, i64 9221120237041090560, i64 %kzb`, ` %x1s = lshr i64 %kb, 30`, ` %x1 = xor i64 %kb, %x1s`, ` %x2 = mul i64 %x1, -4658895280553007687`, ` %x3s = lshr i64 %x2, 27`, ` %x3 = xor i64 %x2, %x3s`, ` %x4 = mul i64 %x3, -7723592293110705685`, ` %x5s = lshr i64 %x4, 31`, ` %x5 = xor i64 %x4, %x5s`, ` %hz = icmp eq i64 %x5, 0`, ` %h = select i1 %hz, i64 1, i64 %x5`, ` %f1s = lshr i64 %h, 44`, ` %f1a = and i64 %f1s, 63`, ` %f1 = shl i64 1, %f1a`, ` %f2s = lshr i64 %h, 50`, ` %f2a = and i64 %f2s, 63`, ` %f2 = shl i64 1, %f2a`, ` %fb = or i64 %f1, %f2`, ` %fp = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 11`, ` %filter = load i64, ptr %fp`, ` %fm = and i64 %filter, %fb`, ` %fin = icmp eq i64 %fm, %fb`, ` br i1 %fin, label %table, label %miss`, `table:`, ` %nbp = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 14`, ` %nb = load ${sz}, ptr %nbp`, ` %eps = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 13`, ` %ents = load ptr, ptr %eps`, ` %linear = icmp eq ${sz} %nb, 0`, ` br i1 %linear, label %scan, label %buckets`,
|
|
2207
|
+
// Small maps keep no bucket table: scan the cached entry hashes.
|
|
2208
|
+
`scan:`, ` %nep = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 9`, ` %ne = load ${sz}, ptr %nep`, ` br label %scan.loop`, `scan.loop:`, ` %si = phi ${sz} [ 0, %scan ], [ %si.next, %scan.next ]`, ` %sdone = icmp eq ${sz} %si, %ne`, ` br i1 %sdone, label %miss, label %scan.entry`, `scan.entry:`, ` %se = getelementptr inbounds %ScrMapEntry, ptr %ents, ${sz} %si`, ` %seh = getelementptr inbounds %ScrMapEntry, ptr %se, i32 0, i32 2`, ` %sh = load i64, ptr %seh`, ` %sk = load i64, ptr %se`, ` %shq = icmp eq i64 %sh, %h`, ` %skq = icmp eq i64 %sk, %kb`, ` %sq = and i1 %shq, %skq`, ` br i1 %sq, label %scan.found, label %scan.next`, `scan.found:`, ` ret ptr %se`, `scan.next:`, ` %si.next = add ${sz} %si, 1`, ` br label %scan.loop`,
|
|
2209
|
+
// Compact tables tag each 24-bit entry index (+1) with the hash's
|
|
2210
|
+
// top byte; wider tables take the runtime lookup.
|
|
2211
|
+
`buckets:`, ` %wide = icmp ugt ${sz} %nb, 16777216`, ` br i1 %wide, label %runtime, label %probe`, `probe:`, ` %bp = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 15`, ` %bk = load ptr, ptr %bp`, ` %mask = sub ${sz} %nb, 1`, ` %ht = lshr i64 %h, 32`, ` %ht32 = trunc i64 %ht to i32`, ` %tag = and i32 %ht32, -16777216`, sz === "i64" ? ` %hi = add i64 %h, 0` : ` %hi = trunc i64 %h to ${sz}`, ` %i0 = and ${sz} %hi, %mask`, ` br label %probe.loop`, `probe.loop:`, ` %pi = phi ${sz} [ %i0, %probe ], [ %pi.next, %probe.next ]`, ` %bep = getelementptr inbounds i32, ptr %bk, ${sz} %pi`, ` %b = load i32, ptr %bep`, ` %bempty = icmp eq i32 %b, 0`, ` br i1 %bempty, label %miss, label %probe.tag`, `probe.tag:`, ` %bt = and i32 %b, -16777216`, ` %btq = icmp eq i32 %bt, %tag`, ` br i1 %btq, label %probe.entry, label %probe.next`, `probe.entry:`, ` %bix = and i32 %b, 16777215`, ` %bix1 = sub i32 %bix, 1`, sz === "i32" ? ` %bi = add i32 %bix1, 0` : ` %bi = zext i32 %bix1 to ${sz}`, ` %pe = getelementptr inbounds %ScrMapEntry, ptr %ents, ${sz} %bi`, ` %peh = getelementptr inbounds %ScrMapEntry, ptr %pe, i32 0, i32 2`, ` %ph = load i64, ptr %peh`, ` %pk = load i64, ptr %pe`, ` %phq = icmp eq i64 %ph, %h`, ` %pkq = icmp eq i64 %pk, %kb`, ` %pq = and i1 %phq, %pkq`, ` br i1 %pq, label %probe.found, label %probe.next`, `probe.found:`, ` ret ptr %pe`, `probe.next:`, ` %pi.inc = add ${sz} %pi, 1`, ` %pi.next = and ${sz} %pi.inc, %mask`, ` br label %probe.loop`, `miss:`, ` ret ptr null`, `runtime:`, ` %r = call ptr @scr_map_entry_f64(ptr %m, double %k) memory(read) nounwind willreturn`, ` ret ptr %r`, `}`, ``);
|
|
2200
2212
|
}
|
|
2201
2213
|
// Map/Set iteration steps read the entries array inline: an index is
|
|
2202
2214
|
// live when it is below the entry count and its entry's cached hash is
|
|
@@ -3604,6 +3616,11 @@ export class LlEmitter {
|
|
|
3604
3616
|
this.B.line(`store i32 0, ptr ${slot}`);
|
|
3605
3617
|
return slot;
|
|
3606
3618
|
}
|
|
3619
|
+
/** The amortized cancellation poll, emitted on the loop's back edge (the
|
|
3620
|
+
* continue target), after the body. A poll in the header would be a loop
|
|
3621
|
+
* exit ahead of the body; LLVM then cannot rotate the loop, so loads that
|
|
3622
|
+
* the body repeats on every iteration (a typed array's length, for one)
|
|
3623
|
+
* stay in the loop. */
|
|
3607
3624
|
emitWorkerLoopCheck(slot) {
|
|
3608
3625
|
if (slot === null)
|
|
3609
3626
|
return;
|
|
@@ -4571,6 +4588,7 @@ export class LlEmitter {
|
|
|
4571
4588
|
this.scalarStringSlices =
|
|
4572
4589
|
this.debug === null ? findScalarStringSlices(fn, this.callLifetimes) : new Map();
|
|
4573
4590
|
this.mapReadLifetimes = findMapReadLifetimes(fn, this.boxedUnionsById, this.callLifetimes);
|
|
4591
|
+
this.readNumberMapWrites = findReadNumberMapWrites(fn);
|
|
4574
4592
|
this.localStackUnions = findLocalStackUnions(fn, this.callLifetimes, this.boxedUnionsById);
|
|
4575
4593
|
this.localStackObjects = this.stackObjects
|
|
4576
4594
|
? findLocalStackObjects(this, fn, this.callLifetimes)
|
|
@@ -5796,7 +5814,7 @@ export class LlEmitter {
|
|
|
5796
5814
|
B.line(`${lenPtr} = getelementptr inbounds %ScrArr, ptr ${arr.name}, i32 0, i32 1`);
|
|
5797
5815
|
this.markMemoryPointer(lenPtr, "array:header");
|
|
5798
5816
|
B.line(`${len} = load ${this.sizeType}, ptr ${lenPtr}${this.fieldAliasAttachment(lenPtr)}`);
|
|
5799
|
-
B.line(`${lenNumber} =
|
|
5817
|
+
B.line(`${lenNumber} = ${sizeToDouble(this.sizeType)} ${this.sizeType} ${len} to double`);
|
|
5800
5818
|
B.line(`${same} = fcmp oeq double ${length.name}, ${lenNumber}`);
|
|
5801
5819
|
B.condBr(same, done, resize);
|
|
5802
5820
|
B.startBlock(resize);
|
|
@@ -6088,15 +6106,15 @@ export class LlEmitter {
|
|
|
6088
6106
|
const lc = B.newLabel("loop.c");
|
|
6089
6107
|
const lb = B.newLabel("loop.b");
|
|
6090
6108
|
const le = B.newLabel("loop.e");
|
|
6109
|
+
const lp = workerBudget !== null ? B.newLabel("loop.p") : lc;
|
|
6091
6110
|
B.br(lc);
|
|
6092
6111
|
B.startBlock(lc);
|
|
6093
|
-
this.emitWorkerLoopCheck(workerBudget);
|
|
6094
6112
|
B.condBr(this.emitCondition(s.cond), lb, le);
|
|
6095
6113
|
B.startBlock(lb);
|
|
6096
6114
|
this.jumpTargets.push({
|
|
6097
6115
|
kind: "loop",
|
|
6098
6116
|
brkLabel: le,
|
|
6099
|
-
contLabel:
|
|
6117
|
+
contLabel: lp,
|
|
6100
6118
|
labels: s.labels,
|
|
6101
6119
|
frameDepth: this.frames.length,
|
|
6102
6120
|
scopeDepth: this.scopes.length,
|
|
@@ -6104,7 +6122,12 @@ export class LlEmitter {
|
|
|
6104
6122
|
});
|
|
6105
6123
|
this.emitBlock(s.body);
|
|
6106
6124
|
this.jumpTargets.pop();
|
|
6107
|
-
B.br(
|
|
6125
|
+
B.br(lp);
|
|
6126
|
+
if (lp !== lc) {
|
|
6127
|
+
B.startBlock(lp);
|
|
6128
|
+
this.emitWorkerLoopCheck(workerBudget);
|
|
6129
|
+
B.br(lc);
|
|
6130
|
+
}
|
|
6108
6131
|
B.startBlock(le);
|
|
6109
6132
|
break;
|
|
6110
6133
|
}
|
|
@@ -6116,7 +6139,6 @@ export class LlEmitter {
|
|
|
6116
6139
|
const le = B.newLabel("loop.e");
|
|
6117
6140
|
B.br(lb);
|
|
6118
6141
|
B.startBlock(lb);
|
|
6119
|
-
this.emitWorkerLoopCheck(workerBudget);
|
|
6120
6142
|
this.jumpTargets.push({
|
|
6121
6143
|
kind: "loop",
|
|
6122
6144
|
brkLabel: le,
|
|
@@ -6130,6 +6152,7 @@ export class LlEmitter {
|
|
|
6130
6152
|
this.jumpTargets.pop();
|
|
6131
6153
|
B.br(lc);
|
|
6132
6154
|
B.startBlock(lc);
|
|
6155
|
+
this.emitWorkerLoopCheck(workerBudget);
|
|
6133
6156
|
B.condBr(this.emitCondition(s.cond), lb, le);
|
|
6134
6157
|
B.startBlock(le);
|
|
6135
6158
|
break;
|
|
@@ -6289,12 +6312,11 @@ export class LlEmitter {
|
|
|
6289
6312
|
B.line(`store ptr ${fresh}, ptr ${slot}`);
|
|
6290
6313
|
}
|
|
6291
6314
|
};
|
|
6292
|
-
const lu = s.update || capturedLets.length > 0 ? B.newLabel("loop.u") : lc;
|
|
6293
|
-
freshenBindings();
|
|
6294
6315
|
const workerBudget = this.workerLoopBudget(s);
|
|
6316
|
+
const lu = s.update || capturedLets.length > 0 || workerBudget !== null ? B.newLabel("loop.u") : lc;
|
|
6317
|
+
freshenBindings();
|
|
6295
6318
|
B.br(lc);
|
|
6296
6319
|
B.startBlock(lc);
|
|
6297
|
-
this.emitWorkerLoopCheck(workerBudget);
|
|
6298
6320
|
if (integerLoop && integerSlot) {
|
|
6299
6321
|
const receiver = this.emitStableReceiver(integerLoop.limitReceiver, []);
|
|
6300
6322
|
const lenPtr = B.tmp();
|
|
@@ -6335,6 +6357,7 @@ export class LlEmitter {
|
|
|
6335
6357
|
B.br(lu);
|
|
6336
6358
|
if (lu !== lc) {
|
|
6337
6359
|
B.startBlock(lu);
|
|
6360
|
+
this.emitWorkerLoopCheck(workerBudget);
|
|
6338
6361
|
freshenBindings();
|
|
6339
6362
|
if (integerLoop && integerSlot) {
|
|
6340
6363
|
const old = B.tmp();
|
|
@@ -6402,7 +6425,6 @@ export class LlEmitter {
|
|
|
6402
6425
|
const workerBudget = this.workerLoopBudget(s);
|
|
6403
6426
|
B.br(lc);
|
|
6404
6427
|
B.startBlock(lc);
|
|
6405
|
-
this.emitWorkerLoopCheck(workerBudget);
|
|
6406
6428
|
const inBounds = B.tmp();
|
|
6407
6429
|
let cur;
|
|
6408
6430
|
if (snapshot && cursor && scratch) {
|
|
@@ -6418,7 +6440,7 @@ export class LlEmitter {
|
|
|
6418
6440
|
B.line(`${lenPtr} = getelementptr inbounds %ScrArr, ptr ${arr.name}, i32 0, i32 1`);
|
|
6419
6441
|
this.markMemoryPointer(lenPtr, "array:header");
|
|
6420
6442
|
B.line(`${rawLen} = load ${this.sizeType}, ptr ${lenPtr}${this.fieldAliasAttachment(lenPtr)}`);
|
|
6421
|
-
B.line(`${len} =
|
|
6443
|
+
B.line(`${len} = ${sizeToDouble(this.sizeType)} ${this.sizeType} ${rawLen} to double`);
|
|
6422
6444
|
B.line(`${inBounds} = fcmp olt double ${i}, ${len}`);
|
|
6423
6445
|
cur = i;
|
|
6424
6446
|
}
|
|
@@ -6476,6 +6498,7 @@ export class LlEmitter {
|
|
|
6476
6498
|
this.jumpTargets.pop();
|
|
6477
6499
|
B.br(lu);
|
|
6478
6500
|
B.startBlock(lu);
|
|
6501
|
+
this.emitWorkerLoopCheck(workerBudget);
|
|
6479
6502
|
if (idxSlot) {
|
|
6480
6503
|
const i2 = B.tmp(), i3 = B.tmp();
|
|
6481
6504
|
B.line(`${i2} = load double, ptr ${idxSlot}`);
|
|
@@ -7192,8 +7215,122 @@ export class LlEmitter {
|
|
|
7192
7215
|
e.name === "region.leave" ||
|
|
7193
7216
|
e.name === "region.release")
|
|
7194
7217
|
return this.emitRegionIntrinsic(e);
|
|
7218
|
+
if (e.name.startsWith("itable."))
|
|
7219
|
+
return this.emitInternTableIntrinsic(e);
|
|
7195
7220
|
return emitIntrinsicExpr(this, e);
|
|
7196
7221
|
}
|
|
7222
|
+
/** InternTable's runtime calls (scr_itable.c). Table and entry handles
|
|
7223
|
+
* are f64 values carrying pointer bits; entry values are 64-bit slots
|
|
7224
|
+
* (double bits, a bool, or a pointer to an immortal value) that the
|
|
7225
|
+
* table neither retains nor releases. Lookups and inserts of array keys
|
|
7226
|
+
* throw a TypeError for keys longer than a table accepts. */
|
|
7227
|
+
emitInternTableIntrinsic(e) {
|
|
7228
|
+
const B = this.B;
|
|
7229
|
+
// The runtime copies keys and stores published values without counts,
|
|
7230
|
+
// so every operand is borrowed.
|
|
7231
|
+
const args = emitBorrowedInputs(this, e.args);
|
|
7232
|
+
if (B.isTerminated())
|
|
7233
|
+
return { name: "", type: e.type };
|
|
7234
|
+
const toPtr = (handle) => {
|
|
7235
|
+
const bits = B.tmp(), ptr = B.tmp();
|
|
7236
|
+
B.line(`${bits} = bitcast double ${handle} to i64`);
|
|
7237
|
+
B.line(`${ptr} = inttoptr i64 ${bits} to ptr`);
|
|
7238
|
+
return ptr;
|
|
7239
|
+
};
|
|
7240
|
+
const toHandle = (ptr) => {
|
|
7241
|
+
const bits = B.tmp(), handle = B.tmp();
|
|
7242
|
+
B.line(`${bits} = ptrtoint ptr ${ptr} to i64`);
|
|
7243
|
+
B.line(`${handle} = bitcast i64 ${bits} to double`);
|
|
7244
|
+
return { name: handle, type: e.type };
|
|
7245
|
+
};
|
|
7246
|
+
const keyCall = (op) => {
|
|
7247
|
+
const kind = e.args[1].type.kind;
|
|
7248
|
+
const key = kind === "string" ? "str" : kind === "array" ? "arr" : "f64";
|
|
7249
|
+
const keyTy = key === "f64" ? "double" : "ptr";
|
|
7250
|
+
const value = op === "insert" ? ", i64" : "";
|
|
7251
|
+
this.declare(`declare ptr @scr_itable_${op}_${key}(ptr, ${keyTy}${value})`);
|
|
7252
|
+
return `@scr_itable_${op}_${key}(ptr ${toPtr(args[0].name)}, ${keyTy} ${args[1].name}`;
|
|
7253
|
+
};
|
|
7254
|
+
switch (e.name) {
|
|
7255
|
+
case "itable.open": {
|
|
7256
|
+
this.declare(`declare ptr @scr_itable_open(ptr, i32)`);
|
|
7257
|
+
const kind = B.tmp(), table = B.tmp();
|
|
7258
|
+
B.line(`${kind} = fptosi double ${args[1].name} to i32`);
|
|
7259
|
+
B.line(`${table} = call ptr @scr_itable_open(ptr ${args[0].name}, i32 ${kind})`);
|
|
7260
|
+
return toHandle(table);
|
|
7261
|
+
}
|
|
7262
|
+
case "itable.find": {
|
|
7263
|
+
const call = keyCall("find");
|
|
7264
|
+
const entry = B.tmp();
|
|
7265
|
+
B.line(`${entry} = call ptr ${call})`);
|
|
7266
|
+
// Array keys longer than a table accepts throw a TypeError.
|
|
7267
|
+
if (e.args[1].type.kind === "array")
|
|
7268
|
+
this.emitPendingCheck();
|
|
7269
|
+
return toHandle(entry);
|
|
7270
|
+
}
|
|
7271
|
+
case "itable.insert": {
|
|
7272
|
+
const value = args[2];
|
|
7273
|
+
const ty = this.llType(value.type);
|
|
7274
|
+
let slot = value.name;
|
|
7275
|
+
if (ty === "double") {
|
|
7276
|
+
slot = B.tmp();
|
|
7277
|
+
B.line(`${slot} = bitcast double ${value.name} to i64`);
|
|
7278
|
+
}
|
|
7279
|
+
else if (ty === "i1") {
|
|
7280
|
+
slot = B.tmp();
|
|
7281
|
+
B.line(`${slot} = zext i1 ${value.name} to i64`);
|
|
7282
|
+
}
|
|
7283
|
+
else if (ty === "ptr") {
|
|
7284
|
+
slot = B.tmp();
|
|
7285
|
+
B.line(`${slot} = ptrtoint ptr ${value.name} to i64`);
|
|
7286
|
+
}
|
|
7287
|
+
else
|
|
7288
|
+
throw new InternalCompilerError(`llvm emitter bug: itable value of type ${ty}`);
|
|
7289
|
+
const call = keyCall("insert");
|
|
7290
|
+
const entry = B.tmp();
|
|
7291
|
+
B.line(`${entry} = call ptr ${call}, i64 ${slot})`);
|
|
7292
|
+
if (e.args[1].type.kind === "array")
|
|
7293
|
+
this.emitPendingCheck();
|
|
7294
|
+
return toHandle(entry);
|
|
7295
|
+
}
|
|
7296
|
+
case "itable.value": {
|
|
7297
|
+
// The handle's bits reach the address through memory: at -O0, x86
|
|
7298
|
+
// FastISel folds inttoptr(bitcast double) into the load's address
|
|
7299
|
+
// without moving the value out of its XMM register. Optimized
|
|
7300
|
+
// builds turn the stack round trip back into one register move.
|
|
7301
|
+
const carrier = B.slot();
|
|
7302
|
+
B.entryAllocas.push(`${carrier} = alloca double`);
|
|
7303
|
+
B.line(`store double ${args[0].name}, ptr ${carrier}`);
|
|
7304
|
+
const bits = B.tmp(), entry = B.tmp();
|
|
7305
|
+
B.line(`${bits} = load i64, ptr ${carrier}`);
|
|
7306
|
+
B.line(`${entry} = inttoptr i64 ${bits} to ptr`);
|
|
7307
|
+
const slot = B.tmp();
|
|
7308
|
+
B.line(`${slot} = load i64, ptr ${entry}, align 8`);
|
|
7309
|
+
const ty = this.llType(e.type);
|
|
7310
|
+
const result = B.tmp();
|
|
7311
|
+
if (ty === "double")
|
|
7312
|
+
B.line(`${result} = bitcast i64 ${slot} to double`);
|
|
7313
|
+
else if (ty === "i1")
|
|
7314
|
+
B.line(`${result} = trunc i64 ${slot} to i1`);
|
|
7315
|
+
else if (ty === "ptr")
|
|
7316
|
+
B.line(`${result} = inttoptr i64 ${slot} to ptr`);
|
|
7317
|
+
else
|
|
7318
|
+
throw new InternalCompilerError(`llvm emitter bug: itable value of type ${ty}`);
|
|
7319
|
+
// Stored values are immortal: owning one adds no count.
|
|
7320
|
+
return isRefCounted(e.type)
|
|
7321
|
+
? this.own({ name: result, type: e.type })
|
|
7322
|
+
: { name: result, type: e.type };
|
|
7323
|
+
}
|
|
7324
|
+
case "itable.size": {
|
|
7325
|
+
this.declare(`declare double @scr_itable_size(ptr)`);
|
|
7326
|
+
const size = B.tmp();
|
|
7327
|
+
B.line(`${size} = call double @scr_itable_size(ptr ${toPtr(args[0].name)})`);
|
|
7328
|
+
return { name: size, type: e.type };
|
|
7329
|
+
}
|
|
7330
|
+
default:
|
|
7331
|
+
throw new InternalCompilerError(`llvm emitter bug: unknown intrinsic ${e.name}`);
|
|
7332
|
+
}
|
|
7333
|
+
}
|
|
7197
7334
|
/** Lifetime regions in modules with lifetimeRegions (llvm/regions.ts).
|
|
7198
7335
|
* Created with the class graph; null elsewhere. */
|
|
7199
7336
|
regions = null;
|