@@ -325,8 +325,10 @@ export class Options {
325325 /** Sets whether a feature is enabled. */
326326 setFeature ( feature : Feature , on : bool = true ) : void {
327327 if ( on ) {
328+ // Enabling Shared Everything also enables Threads and GC
329+ if ( feature & Feature . SharedEverything ) feature |= Feature . Threads | Feature . GC ;
328330 // Enabling Stringref also enables GC
329- if ( feature & Feature . Stringref ) feature |= Feature . GC ;
331+ if ( feature & Feature . Strings ) feature |= Feature . GC ;
330332 // Enabling GC also enables Reference Types
331333 if ( feature & Feature . GC ) feature |= Feature . ReferenceTypes ;
332334 // Enabling Relaxed SIMD also enables SIMD
@@ -336,9 +338,11 @@ export class Options {
336338 // Disabling Reference Types also disables GC
337339 if ( feature & Feature . ReferenceTypes ) feature |= Feature . GC ;
338340 // Disabling GC also disables Stringref
339- if ( feature & Feature . GC ) feature |= Feature . Stringref ;
341+ if ( feature & Feature . GC ) feature |= Feature . Strings ;
340342 // Disabling SIMD also disables Relaxed SIMD
341343 if ( feature & Feature . Simd ) feature |= Feature . RelaxedSimd ;
344+ // Disabling Threads or GC also disables Shared Everything
345+ if ( feature & ( Feature . Threads | Feature . GC ) ) feature |= Feature . SharedEverything ;
342346 this . features &= ~ feature ;
343347 }
344348 }
@@ -515,7 +519,8 @@ export class Compiler extends DiagnosticEmitter {
515519 if ( options . hasFeature ( Feature . Memory64 ) ) featureFlags |= FeatureFlags . Memory64 ;
516520 if ( options . hasFeature ( Feature . RelaxedSimd ) ) featureFlags |= FeatureFlags . RelaxedSIMD ;
517521 if ( options . hasFeature ( Feature . ExtendedConst ) ) featureFlags |= FeatureFlags . ExtendedConst ;
518- if ( options . hasFeature ( Feature . Stringref ) ) featureFlags |= FeatureFlags . Stringref ;
522+ if ( options . hasFeature ( Feature . Strings ) ) featureFlags |= FeatureFlags . Strings ;
523+ if ( options . hasFeature ( Feature . SharedEverything ) ) featureFlags |= FeatureFlags . SharedEverything ;
519524 module . setFeatures ( featureFlags ) ;
520525
521526 // set up the main start function
@@ -534,10 +539,16 @@ export class Compiler extends DiagnosticEmitter {
534539 let resolver = this . resolver ;
535540 let hasShadowStack = options . stackSize > 0 ; // implies runtime=incremental
536541
542+ // Register a dummy memory so Binaryen's EffectAnalyzer can read
543+ // memory.shared on loads/stores emitted during compilation. The real
544+ // memory is installed by `initDefaultMemory` below, which can't run
545+ // here: it needs `memoryOffset` (known only after data layout) and
546+ // emits diagnostics / exports that must happen exactly once.
547+ this . initDummyMemory ( ) ;
548+
537549 // initialize lookup maps, built-ins, imports, exports, etc.
538550 this . program . initialize ( ) ;
539551
540-
541552 // Binaryen treats all function references as being leaked to the outside world when
542553 // the module isn't marked as closed-world (see WebAssembly/binaryen#7135). Therefore,
543554 // we should mark the module as closed-world when we're definitely sure it is.
@@ -762,6 +773,19 @@ export class Compiler extends DiagnosticEmitter {
762773 return module ;
763774 }
764775
776+ private initDummyMemory ( ) : void {
777+ let options = this . options ;
778+ this . module . setMemory (
779+ 0 ,
780+ Module . UNLIMITED_MEMORY ,
781+ [ ] ,
782+ options . target ,
783+ null ,
784+ CommonNames . DefaultMemory ,
785+ options . sharedMemory
786+ ) ;
787+ }
788+
765789 private initDefaultMemory ( memoryOffset : i64 ) : void {
766790 this . memoryOffset = memoryOffset ;
767791
@@ -1524,7 +1548,7 @@ export class Compiler extends DiagnosticEmitter {
15241548
15251549 private ensureEnumToString ( enumElement : Enum , reportNode : Node ) : string | null {
15261550 if ( enumElement . toStringFunctionName ) return enumElement . toStringFunctionName ;
1527-
1551+
15281552 if ( ! this . compileEnum ( enumElement ) ) return null ;
15291553 if ( enumElement . is ( CommonFlags . Const ) ) {
15301554 this . errorRelated (
@@ -2583,7 +2607,7 @@ export class Compiler extends DiagnosticEmitter {
25832607 // (then │ │ (body) │
25842608 // (?block $continue │ │ if loops: (incrementor) ─────┘
25852609 // (body) │ │ recompile body?
2586- // ) ├◄┘
2610+ // ) ├◄┘
25872611 // (incrementor) ┌◄┘
25882612 // (br $loop)
25892613 // )
@@ -2872,17 +2896,17 @@ export class Compiler extends DiagnosticEmitter {
28722896 // Compile the condition (always executes)
28732897 let condExpr = this . compileExpression ( statement . condition , Type . auto ) ;
28742898 let condType = this . currentType ;
2875-
2899+
28762900 // Shortcut if there are no cases
28772901 if ( ! numCases ) return module . drop ( condExpr ) ;
2878-
2902+
28792903 // Assign the condition to a temporary local as we compare it multiple times
28802904 let outerFlow = this . currentFlow ;
28812905 let tempLocal = outerFlow . getTempLocal ( condType ) ;
28822906 let tempLocalIndex = tempLocal . index ;
28832907 let breaks = new Array < ExpressionRef > ( 1 + numCases ) ;
28842908 breaks [ 0 ] = module . local_set ( tempLocalIndex , condExpr , condType . isManaged ) ;
2885-
2909+
28862910 // Make one br_if per labeled case and leave it to Binaryen to optimize the
28872911 // sequence of br_ifs to a br_table according to optimization levels
28882912 let breakIndex = 1 ;
@@ -2894,7 +2918,7 @@ export class Compiler extends DiagnosticEmitter {
28942918 defaultIndex = i ;
28952919 continue ;
28962920 }
2897-
2921+
28982922 // Compile the equality expression for this case
28992923 const left = statement . condition ;
29002924 const leftExpr = module . local_get ( tempLocalIndex , condType . toRef ( ) ) ;
@@ -2909,7 +2933,7 @@ export class Compiler extends DiagnosticEmitter {
29092933 condType ,
29102934 statement
29112935 ) ;
2912-
2936+
29132937 // Add it to the list of breaks
29142938 breaks [ breakIndex ++ ] = module . br ( `case${ i } |${ label } ` , equalityExpr ) ;
29152939 }
@@ -3863,7 +3887,7 @@ export class Compiler extends DiagnosticEmitter {
38633887 expression : BinaryExpression ,
38643888 contextualType : Type ,
38653889 ) : ExpressionRef {
3866-
3890+
38673891 const left = expression . left ;
38683892 const leftExpr = this . compileExpression ( left , contextualType ) ;
38693893 const leftType = this . currentType ;
@@ -3881,9 +3905,9 @@ export class Compiler extends DiagnosticEmitter {
38813905 ) ;
38823906 }
38833907
3884- /**
3908+ /**
38853909 * compile `==` `===` `!=` `!==` BinaryExpression, from previously compiled left and right expressions.
3886- *
3910+ *
38873911 * This is split from `compileCommutativeCompareBinaryExpression` so that the logic can be reused
38883912 * for switch cases in `compileSwitchStatement`, where the left expression only should be compiled once.
38893913 */
@@ -3901,15 +3925,15 @@ export class Compiler extends DiagnosticEmitter {
39013925
39023926 let module = this . module ;
39033927 let operatorString = operatorTokenToString ( operator ) ;
3904-
3928+
39053929 // check operator overload
39063930 const operatorKind = OperatorKind . fromBinaryToken ( operator ) ;
39073931 const leftOverload = leftType . lookupOverload ( operatorKind , this . program ) ;
39083932 const rightOverload = rightType . lookupOverload ( operatorKind , this . program ) ;
39093933 if ( leftOverload && rightOverload && leftOverload != rightOverload ) {
39103934 this . error (
39113935 DiagnosticCode . Ambiguous_operator_overload_0_conflicting_overloads_1_and_2 ,
3912- reportNode . range ,
3936+ reportNode . range ,
39133937 operatorString ,
39143938 leftOverload . internalName ,
39153939 rightOverload . internalName
@@ -3999,7 +4023,7 @@ export class Compiler extends DiagnosticEmitter {
39994023
40004024 leftExpr = this . compileExpression ( left , contextualType ) ;
40014025 leftType = this . currentType ;
4002-
4026+
40034027 // check operator overload
40044028 const operatorKind = OperatorKind . fromBinaryToken ( operator ) ;
40054029 const leftOverload = leftType . lookupOverload ( operatorKind , this . program ) ;
@@ -4070,7 +4094,7 @@ export class Compiler extends DiagnosticEmitter {
40704094 return this . compileNonCommutativeCompareBinaryExpression ( expression , contextualType ) ;
40714095 }
40724096 case Token . Equals_Equals_Equals :
4073- case Token . Equals_Equals :
4097+ case Token . Equals_Equals :
40744098 case Token . Exclamation_Equals_Equals :
40754099 case Token . Exclamation_Equals : {
40764100 return this . compileCommutativeCompareBinaryExpression ( expression , contextualType ) ;
@@ -6352,13 +6376,13 @@ export class Compiler extends DiagnosticEmitter {
63526376 if ( numArguments < numParams ) {
63536377 return argumentExpressions ;
63546378 }
6355-
6379+
63566380 // make an array literal expression from the rest args
63576381 let elements = argumentExpressions . slice ( numParams - 1 ) ;
63586382 let range = new Range ( elements [ 0 ] . range . start , elements [ elements . length - 1 ] . range . end ) ;
63596383 range . source = reportNode . range . source ;
63606384 let arrExpr = new ArrayLiteralExpression ( elements , range ) ;
6361-
6385+
63626386 // return the original args, but replace the rest args with the array
63636387 const exprs = argumentExpressions . slice ( 0 , numParams - 1 ) ;
63646388 exprs . push ( arrExpr ) ;
@@ -6622,9 +6646,9 @@ export class Compiler extends DiagnosticEmitter {
66226646 let initializer = declaration . initializer ;
66236647 let initExpr : ExpressionRef ;
66246648 if ( declaration . parameterKind === ParameterKind . Rest ) {
6625- const arrExpr = new ArrayLiteralExpression ( [ ] , declaration . range . atEnd ) ;
6649+ const arrExpr = new ArrayLiteralExpression ( [ ] , declaration . range . atEnd ) ;
66266650 initExpr = this . compileArrayLiteral ( arrExpr , type , Constraints . ConvExplicit ) ;
6627- initExpr = module . local_set ( operandIndex , initExpr , type . isManaged ) ;
6651+ initExpr = module . local_set ( operandIndex , initExpr , type . isManaged ) ;
66286652 } else if ( initializer ) {
66296653 initExpr = this . compileExpression (
66306654 initializer ,
@@ -7869,7 +7893,7 @@ export class Compiler extends DiagnosticEmitter {
78697893 stmts . length = 1 ;
78707894 stmts . push (
78717895 module . i32 ( 1 )
7872- ) ;
7896+ ) ;
78737897 module . removeFunction ( name ) ;
78747898 module . addFunction ( name , sizeType , TypeRef . I32 , [ TypeRef . I32 ] , module . block ( null , stmts , TypeRef . I32 ) ) ;
78757899 }
0 commit comments