Skip to content

Commit 4e0239c

Browse files
committed
Upgraded to Binaryen 125
1 parent dc766bc commit 4e0239c

File tree

296 files changed

+464652
-123567
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

296 files changed

+464652
-123567
lines changed

src/compiler.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -651,11 +651,9 @@ export class Compiler extends DiagnosticEmitter {
651651
}
652652
}
653653

654-
// finalize runtime features (RTTI must be compiled here as it affects memory layout)
654+
// finalize runtime features (RTTI only - visitGlobals/visitMembers are compiled after shadow stack pass)
655655
module.removeGlobal(BuiltinNames.rtti_base);
656656
if (this.runtimeFeatures & RuntimeFeatures.Rtti) compileRTTI(this);
657-
// NOTE: compileVisitGlobals and compileVisitMembers are deferred until after
658-
// custom passes (like shadow stack) that may trigger additional compilations
659657

660658
let memoryOffset = i64_align(this.memoryOffset, options.usizeType.byteSize);
661659

@@ -757,18 +755,24 @@ export class Compiler extends DiagnosticEmitter {
757755
}
758756
}
759757

760-
// Run custom passes
758+
// Run shadow stack pass first (may trigger compilation of functions that need visit functions)
761759
if (hasShadowStack) {
762760
this.shadowStack.walkModule();
763761
}
764-
if (program.lookup("ASC_RTRACE") != null) {
765-
new RtraceMemory(this).walkModule();
766-
}
767762

768-
// Finalize visit functions after custom passes that may trigger additional compilations
763+
// Compile visit functions after shadow stack pass (which may have set runtimeFeatures flags)
769764
if (this.runtimeFeatures & RuntimeFeatures.visitGlobals) compileVisitGlobals(this);
770765
if (this.runtimeFeatures & RuntimeFeatures.visitMembers) compileVisitMembers(this);
771766

767+
// Run shadow stack pass again with a fresh instance to transform any __tostack calls in visit functions
768+
if (hasShadowStack && (this.runtimeFeatures & (RuntimeFeatures.visitGlobals | RuntimeFeatures.visitMembers))) {
769+
new ShadowStackPass(this).walkModule();
770+
}
771+
772+
if (program.lookup("ASC_RTRACE") != null) {
773+
new RtraceMemory(this).walkModule();
774+
}
775+
772776
return module;
773777
}
774778

src/module.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,20 +271,28 @@ export const enum ExpressionId {
271271
TableSet = 47 /* _BinaryenTableSetId */,
272272
TableSize = 48 /* _BinaryenTableSizeId */,
273273
TableGrow = 49 /* _BinaryenTableGrowId */,
274+
TableFill = 50 /* _BinaryenTableFillId */,
275+
TableCopy = 51 /* _BinaryenTableCopyId */,
276+
TableInit = 52 /* _BinaryenTableInitId */,
274277
Try = 54 /* _BinaryenTryId */,
278+
TryTable = 55 /* _BinaryenTryTableId */,
275279
Throw = 56 /* _BinaryenThrowId */,
276280
Rethrow = 57 /* _BinaryenRethrowId */,
281+
ThrowRef = 58 /* _BinaryenThrowRefId */,
277282
TupleMake = 59 /* _BinaryenTupleMakeId */,
278283
TupleExtract = 60 /* _BinaryenTupleExtractId */,
279284
RefI31 = 61 /* _BinaryenRefI31Id */,
280285
I31Get = 62 /* _BinaryenI31GetId */,
281286
CallRef = 63 /* _BinaryenCallRefId */,
282287
RefTest = 64 /* _BinaryenRefTestId */,
283288
RefCast = 65 /* _BinaryenRefCastId */,
289+
RefGetDesc = 66 /* _BinaryenRefGetDescId */,
284290
BrOn = 67 /* _BinaryenBrOnId */,
285291
StructNew = 68 /* _BinaryenStructNewId */,
286292
StructGet = 69 /* _BinaryenStructGetId */,
287293
StructSet = 70 /* _BinaryenStructSetId */,
294+
StructRMW = 71 /* _BinaryenStructRMWId */,
295+
StructCmpxchg = 72 /* _BinaryenStructCmpxchgId */,
288296
ArrayNew = 73 /* _BinaryenArrayNewId */,
289297
ArrayNewData = 74 /* _BinaryenArrayNewDataId */,
290298
ArrayNewElem = 75 /* _BinaryenArrayNewElemId */,
@@ -304,7 +312,13 @@ export const enum ExpressionId {
304312
StringConcat = 91 /* _BinaryenStringConcatId */,
305313
StringEq = 92 /* _BinaryenStringEqId */,
306314
StringWTF16Get = 94 /* _BinaryenStringWTF16GetId */,
307-
StringSliceWTF = 95 /* _BinaryenStringSliceWTFId */
315+
StringSliceWTF = 95 /* _BinaryenStringSliceWTFId */,
316+
ContNew = 96 /* _BinaryenContNewId */,
317+
ContBind = 97 /* _BinaryenContBindId */,
318+
Suspend = 98 /* _BinaryenSuspendId */,
319+
Resume = 99 /* _BinaryenResumeId */,
320+
ResumeThrow = 100 /* _BinaryenResumeThrowId */,
321+
StackSwitch = 101 /* _BinaryenStackSwitchId */
308322
}
309323

310324
/** Binaryen external kind constants. */

src/passes/shadowstack.ts

Lines changed: 85 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ import {
109109
_BinaryenFunctionSetBody,
110110
_BinaryenGetExport,
111111
_BinaryenGetFunction,
112+
_BinaryenGetFunctionByIndex,
113+
_BinaryenGetNumFunctions,
112114
_BinaryenLocalSetGetIndex,
113115
_BinaryenLocalSetGetValue,
114116
_BinaryenLocalSetIsTee,
@@ -322,7 +324,7 @@ export class ShadowStackPass extends Pass {
322324
/** Makes a check that the current stack pointer is valid. */
323325
makeStackCheck(): ExpressionRef {
324326
let module = this.module;
325-
if (!this.hasStackCheckFunction) {
327+
if (!this.hasStackCheckFunction && !module.hasFunction("~stack_check")) {
326328
this.hasStackCheckFunction = true;
327329
module.addFunction("~stack_check", TypeRef.None, TypeRef.None, null,
328330
module.if(
@@ -573,65 +575,96 @@ export class ShadowStackPass extends Pass {
573575

574576
/** @override */
575577
walkModule(): void {
576-
// Run the pass normally
577-
super.walkModule();
578-
579-
// Instrument returns in functions utilizing stack slots
578+
// Walk functions in a loop until no new functions are added.
579+
// This is necessary because transforming __tostack calls and instrumenting
580+
// functions may trigger compilation of new functions (e.g., via makeStackCheck -> makeStaticAbort).
581+
let moduleRef = this.module.ref;
580582
let module = this.module;
581-
let instrumentReturns = new InstrumentReturns(this);
582-
for (let _keys = Map_keys(this.slotMaps), i = 0, k = _keys.length; i < k; ++i) {
583-
let func = _keys[i];
584-
let slotMap = changetype<SlotMap>(this.slotMaps.get(func));
585-
let frameSize = slotMap.size * this.ptrSize;
583+
let lastNumFunctions: Index = 0;
584+
let iteration = 0;
586585

587-
// Instrument function returns
588-
instrumentReturns.frameSize = frameSize;
589-
instrumentReturns.walkFunction(func);
586+
// Set of functions that have already been instrumented
587+
let instrumentedFunctions = new Set<FunctionRef>();
590588

591-
// Instrument function entry
592-
let stmts = new Array<ExpressionRef>();
593-
// __stack_pointer -= frameSize
594-
stmts.push(
595-
this.makeStackOffset(-frameSize)
596-
);
597-
// memory.fill(__stack_pointer, 0, frameSize)
598-
this.makeStackFill(frameSize, stmts);
599-
600-
// Handle implicit return
601-
let body = _BinaryenFunctionGetBody(func);
602-
let bodyType = _BinaryenExpressionGetType(body);
603-
if (bodyType == TypeRef.Unreachable) {
604-
// body
605-
stmts.push(
606-
body
607-
);
608-
} else if (bodyType == TypeRef.None) {
609-
// body
610-
stmts.push(
611-
body
612-
);
613-
// __stack_pointer += frameSize
614-
stmts.push(
615-
this.makeStackOffset(+frameSize)
616-
);
617-
} else {
618-
let temp = this.getSharedTemp(func, bodyType);
619-
// t = body
620-
stmts.push(
621-
module.local_set(temp, body, false)
622-
);
623-
// __stack_pointer += frameSize
624-
stmts.push(
625-
this.makeStackOffset(+frameSize)
626-
);
627-
// -> t
589+
while (true) {
590+
let currentNumFunctions = _BinaryenGetNumFunctions(moduleRef);
591+
if (currentNumFunctions == lastNumFunctions) break;
592+
593+
// Walk only the newly added functions (from lastNumFunctions to currentNumFunctions)
594+
for (let i = lastNumFunctions; i < currentNumFunctions; ++i) {
595+
this.walkFunction(_BinaryenGetFunctionByIndex(moduleRef, i));
596+
}
597+
598+
// Instrument returns and entries for functions with slots that haven't been instrumented yet
599+
let instrumentReturns = new InstrumentReturns(this);
600+
for (let _keys = Map_keys(this.slotMaps), i = 0, k = _keys.length; i < k; ++i) {
601+
let func = _keys[i];
602+
if (instrumentedFunctions.has(func)) continue;
603+
instrumentedFunctions.add(func);
604+
605+
let slotMap = changetype<SlotMap>(this.slotMaps.get(func));
606+
let frameSize = slotMap.size * this.ptrSize;
607+
608+
// Instrument function returns
609+
instrumentReturns.frameSize = frameSize;
610+
instrumentReturns.walkFunction(func);
611+
612+
// Instrument function entry
613+
let stmts = new Array<ExpressionRef>();
614+
// __stack_pointer -= frameSize
628615
stmts.push(
629-
module.local_get(temp, bodyType)
616+
this.makeStackOffset(-frameSize)
630617
);
618+
// memory.fill(__stack_pointer, 0, frameSize)
619+
this.makeStackFill(frameSize, stmts);
620+
621+
// Handle implicit return
622+
let body = _BinaryenFunctionGetBody(func);
623+
let bodyType = _BinaryenExpressionGetType(body);
624+
if (bodyType == TypeRef.Unreachable) {
625+
// body
626+
stmts.push(
627+
body
628+
);
629+
} else if (bodyType == TypeRef.None) {
630+
// body
631+
stmts.push(
632+
body
633+
);
634+
// __stack_pointer += frameSize
635+
stmts.push(
636+
this.makeStackOffset(+frameSize)
637+
);
638+
} else {
639+
let temp = this.getSharedTemp(func, bodyType);
640+
// t = body
641+
stmts.push(
642+
module.local_set(temp, body, false)
643+
);
644+
// __stack_pointer += frameSize
645+
stmts.push(
646+
this.makeStackOffset(+frameSize)
647+
);
648+
// -> t
649+
stmts.push(
650+
module.local_get(temp, bodyType)
651+
);
652+
}
653+
_BinaryenFunctionSetBody(func, module.flatten(stmts, bodyType));
654+
}
655+
656+
lastNumFunctions = currentNumFunctions;
657+
iteration++;
658+
659+
// Safety limit to prevent infinite loops
660+
if (iteration > 100) {
661+
throw new Error("ShadowStackPass: too many iterations, possible infinite loop");
631662
}
632-
_BinaryenFunctionSetBody(func, module.flatten(stmts, bodyType));
633663
}
634664

665+
// Walk globals (only once, since they don't trigger new function compilation)
666+
this.walkGlobals();
667+
635668
// Update functions we added more locals to
636669
// TODO: _BinaryenFunctionAddVar ?
637670
for (let _keys = Map_keys(this.tempMaps), i = 0, k = _keys.length; i < k; ++i) {

0 commit comments

Comments
 (0)