@@ -57,7 +57,8 @@ void WasmValidator::visitBlock(Block *curr) {
5757 }
5858 }
5959 }
60- breakTargets[curr->name ].pop_back ();
60+ breakTargets.erase (curr->name );
61+ namedBreakTargets.erase (curr->name );
6162 }
6263 if (curr->list .size () > 1 ) {
6364 for (Index i = 0 ; i < curr->list .size () - 1 ; i++) {
@@ -88,7 +89,8 @@ void WasmValidator::visitBlock(Block *curr) {
8889void WasmValidator::visitLoop (Loop *curr) {
8990 if (curr->name .is ()) {
9091 noteLabelName (curr->name );
91- breakTargets[curr->name ].pop_back ();
92+ breakTargets.erase (curr->name );
93+ namedBreakTargets.erase (curr->name );
9294 if (breakInfos.count (curr) > 0 ) {
9395 auto & info = breakInfos[curr];
9496 shouldBeEqual (info.arity , Index (0 ), curr, " breaks to a loop cannot pass a value" );
@@ -120,15 +122,20 @@ void WasmValidator::visitIf(If *curr) {
120122}
121123
122124void WasmValidator::noteBreak (Name name, Expression* value, Expression* curr) {
125+ if (!BranchUtils::isBranchTaken (curr)) {
126+ // if not actually taken, just note the name
127+ namedBreakTargets.insert (name);
128+ return ;
129+ }
123130 WasmType valueType = none;
124131 Index arity = 0 ;
125132 if (value) {
126133 valueType = value->type ;
127134 shouldBeUnequal (valueType, none, curr, " breaks must have a valid value" );
128135 arity = 1 ;
129136 }
130- if (!shouldBeTrue (breakTargets[name]. size ( ) > 0 , curr, " all break targets must be valid" )) return ;
131- auto * target = breakTargets[name]. back () ;
137+ if (!shouldBeTrue (breakTargets. count (name ) > 0 , curr, " all break targets must be valid" )) return ;
138+ auto * target = breakTargets[name];
132139 if (breakInfos.count (target) == 0 ) {
133140 breakInfos[target] = BreakInfo (valueType, arity);
134141 } else {
@@ -146,23 +153,17 @@ void WasmValidator::noteBreak(Name name, Expression* value, Expression* curr) {
146153 }
147154}
148155void WasmValidator::visitBreak (Break *curr) {
149- // note breaks (that are actually taken)
150- if (BranchUtils::isBranchTaken (curr)) {
151- noteBreak (curr->name , curr->value , curr);
152- }
156+ noteBreak (curr->name , curr->value , curr);
153157 if (curr->condition ) {
154158 shouldBeTrue (curr->condition ->type == unreachable || curr->condition ->type == i32 , curr, " break condition must be i32" );
155159 }
156160}
157161
158162void WasmValidator::visitSwitch (Switch *curr) {
159- // note breaks (that are actually taken)
160- if (BranchUtils::isBranchTaken (curr)) {
161- for (auto & target : curr->targets ) {
162- noteBreak (target, curr->value , curr);
163- }
164- noteBreak (curr->default_ , curr->value , curr);
163+ for (auto & target : curr->targets ) {
164+ noteBreak (target, curr->value , curr);
165165 }
166+ noteBreak (curr->default_ , curr->value , curr);
166167 shouldBeTrue (curr->condition ->type == unreachable || curr->condition ->type == i32 , curr, " br_table condition must be i32" );
167168}
168169void WasmValidator::visitCall (Call *curr) {
@@ -467,7 +468,7 @@ void WasmValidator::visitGlobal(Global* curr) {
467468 shouldBeTrue (curr->init != nullptr , curr->name , " global init must be non-null" );
468469 shouldBeTrue (curr->init ->is <Const>() || curr->init ->is <GetGlobal>(), curr->name , " global init must be valid" );
469470 if (!shouldBeEqual (curr->type , curr->init ->type , curr->init , " global init must have correct type" )) {
470- std::cerr << " (on global " << curr->name << ' \n ' ;
471+ std::cerr << " (on global " << curr->name << " ) \n " ;
471472 }
472473}
473474
@@ -480,6 +481,9 @@ void WasmValidator::visitFunction(Function *curr) {
480481 if (returnType != unreachable) {
481482 shouldBeEqual (curr->result , returnType, curr->body , " function result must match, if function has returns" );
482483 }
484+ if (!shouldBeTrue (namedBreakTargets.empty (), curr->body , " all named break targets must exist (even if not taken)" )) {
485+ std::cerr << " (on label " << *namedBreakTargets.begin () << " )\n " ;
486+ }
483487 returnType = unreachable;
484488 labelNames.clear ();
485489}
0 commit comments