@@ -172,6 +172,18 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
172
172
Instructions,
173
173
} CurrentState = FileStart;
174
174
175
+ // For ensuring blocks are properly nested.
176
+ enum NestingType {
177
+ Function,
178
+ Block,
179
+ Loop,
180
+ Try,
181
+ If,
182
+ Else,
183
+ Undefined,
184
+ };
185
+ std::vector<NestingType> NestingStack;
186
+
175
187
// We track this to see if a .functype following a label is the same,
176
188
// as this is how we recognize the start of a function.
177
189
MCSymbol *LastLabel = nullptr ;
@@ -184,10 +196,6 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
184
196
setAvailableFeatures (ComputeAvailableFeatures (STI.getFeatureBits ()));
185
197
}
186
198
187
- void addSignature (std::unique_ptr<wasm::WasmSignature> &&Sig) {
188
- Signatures.push_back (std::move (Sig));
189
- }
190
-
191
199
#define GET_ASSEMBLER_HEADER
192
200
#include " WebAssemblyGenAsmMatcher.inc"
193
201
@@ -197,10 +205,60 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
197
205
llvm_unreachable (" ParseRegister is not implemented." );
198
206
}
199
207
200
- bool error (const StringRef &Msg, const AsmToken &Tok) {
208
+ bool error (const Twine &Msg, const AsmToken &Tok) {
201
209
return Parser.Error (Tok.getLoc (), Msg + Tok.getString ());
202
210
}
203
211
212
+ bool error (const Twine &Msg) {
213
+ return Parser.Error (Lexer.getTok ().getLoc (), Msg);
214
+ }
215
+
216
+ void addSignature (std::unique_ptr<wasm::WasmSignature> &&Sig) {
217
+ Signatures.push_back (std::move (Sig));
218
+ }
219
+
220
+ std::pair<StringRef, StringRef> nestingString (NestingType NT) {
221
+ switch (NT) {
222
+ case Function:
223
+ return {" function" , " end_function" };
224
+ case Block:
225
+ return {" block" , " end_block" };
226
+ case Loop:
227
+ return {" loop" , " end_loop" };
228
+ case Try:
229
+ return {" try" , " end_try" };
230
+ case If:
231
+ return {" if" , " end_if" };
232
+ case Else:
233
+ return {" else" , " end_if" };
234
+ default :
235
+ llvm_unreachable (" unknown NestingType" );
236
+ }
237
+ }
238
+
239
+ void push (NestingType NT) { NestingStack.push_back (NT); }
240
+
241
+ bool pop (StringRef Ins, NestingType NT1, NestingType NT2 = Undefined) {
242
+ if (NestingStack.empty ())
243
+ return error (Twine (" End of block construct with no start: " ) + Ins);
244
+ auto Top = NestingStack.back ();
245
+ if (Top != NT1 && Top != NT2)
246
+ return error (Twine (" Block construct type mismatch, expected: " ) +
247
+ nestingString (Top).second + " , instead got: " + Ins);
248
+ NestingStack.pop_back ();
249
+ return false ;
250
+ }
251
+
252
+ bool ensureEmptyNestingStack () {
253
+ auto err = !NestingStack.empty ();
254
+ while (!NestingStack.empty ()) {
255
+ error (Twine (" Unmatched block construct(s) at function end: " ) +
256
+ nestingString (NestingStack.back ()).first );
257
+ NestingStack.pop_back ();
258
+ }
259
+ return err;
260
+ }
261
+
204
262
bool isNext (AsmToken::TokenKind Kind) {
205
263
auto Ok = Lexer.is (Kind);
206
264
if (Ok)
@@ -327,6 +385,45 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
327
385
// If no '.', there is no type prefix.
328
386
auto BaseName = NamePair.second .empty () ? NamePair.first : NamePair.second ;
329
387
388
+ // If this instruction is part of a control flow structure, ensure
389
+ // proper nesting.
390
+ if (BaseName == " block" ) {
391
+ push (Block);
392
+ } else if (BaseName == " loop" ) {
393
+ push (Loop);
394
+ } else if (BaseName == " try" ) {
395
+ push (Try);
396
+ } else if (BaseName == " if" ) {
397
+ push (If);
398
+ } else if (BaseName == " else" ) {
399
+ if (pop (BaseName, If))
400
+ return true ;
401
+ push (Else);
402
+ } else if (BaseName == " catch" ) {
403
+ if (pop (BaseName, Try))
404
+ return true ;
405
+ push (Try);
406
+ } else if (BaseName == " catch_all" ) {
407
+ if (pop (BaseName, Try))
408
+ return true ;
409
+ push (Try);
410
+ } else if (BaseName == " end_if" ) {
411
+ if (pop (BaseName, If, Else))
412
+ return true ;
413
+ } else if (BaseName == " end_try" ) {
414
+ if (pop (BaseName, Try))
415
+ return true ;
416
+ } else if (BaseName == " end_loop" ) {
417
+ if (pop (BaseName, Loop))
418
+ return true ;
419
+ } else if (BaseName == " end_block" ) {
420
+ if (pop (BaseName, Block))
421
+ return true ;
422
+ } else if (BaseName == " end_function" ) {
423
+ if (pop (BaseName, Function) || ensureEmptyNestingStack ())
424
+ return true ;
425
+ }
426
+
330
427
while (Lexer.isNot (AsmToken::EndOfStatement)) {
331
428
auto &Tok = Lexer.getTok ();
332
429
switch (Tok.getKind ()) {
@@ -476,7 +573,10 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
476
573
TOut.getStreamer ().getContext ().getOrCreateSymbol (SymName));
477
574
if (CurrentState == Label && WasmSym == LastLabel) {
478
575
// This .functype indicates a start of a function.
576
+ if (ensureEmptyNestingStack ())
577
+ return true ;
479
578
CurrentState = FunctionStart;
579
+ push (Function);
480
580
}
481
581
auto Signature = make_unique<wasm::WasmSignature>();
482
582
if (parseSignature (Signature.get ()))
@@ -565,6 +665,8 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
565
665
}
566
666
llvm_unreachable (" Implement any new match types added!" );
567
667
}
668
+
669
+ void onEndOfFile () override { ensureEmptyNestingStack (); }
568
670
};
569
671
} // end anonymous namespace
570
672
0 commit comments