Skip to content

Commit ef01de5

Browse files
authored
[interpreter] Refactor parser to handle select & call_indirect correctly (#1567)
1 parent 937fc7d commit ef01de5

File tree

3 files changed

+67
-70
lines changed

3 files changed

+67
-70
lines changed

interpreter/text/parser.mly

Lines changed: 30 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -366,12 +366,16 @@ align_opt :
366366

367367
/* Instructions & Expressions */
368368

369-
instr :
369+
instr_list :
370+
| /* empty */ { fun c -> [] }
371+
| instr1 instr_list { fun c -> $1 c @ $2 c }
372+
| select_instr_instr_list { $1 }
373+
| call_instr_instr_list { $1 }
374+
375+
instr1 :
370376
| plain_instr { let at = at () in fun c -> [$1 c @@ at] }
371-
| select_instr_instr { fun c -> let e, es = $1 c in e :: es }
372-
| call_instr_instr { fun c -> let e, es = $1 c in e :: es }
373377
| block_instr { let at = at () in fun c -> [$1 c @@ at] }
374-
| expr { $1 } /* Sugar */
378+
| expr { $1 } /* Sugar */
375379

376380
plain_instr :
377381
| UNREACHABLE { fun c -> unreachable }
@@ -442,89 +446,51 @@ plain_instr :
442446
| VEC_REPLACE NAT { let at = at () in fun c -> $1 (vec_lane_index $2 at) }
443447

444448

445-
select_instr :
446-
| SELECT select_instr_results
447-
{ let at = at () in fun c -> let b, ts = $2 in
448-
select (if b then (Some ts) else None) @@ at }
449-
450-
select_instr_results :
451-
| LPAR RESULT value_type_list RPAR select_instr_results
452-
{ let _, ts = $5 in true, $3 @ ts }
453-
| /* empty */
454-
{ false, [] }
455-
456-
select_instr_instr :
457-
| SELECT select_instr_results_instr
449+
select_instr_instr_list :
450+
| SELECT select_instr_results_instr_list
458451
{ let at1 = ati 1 in
459452
fun c -> let b, ts, es = $2 c in
460-
select (if b then (Some ts) else None) @@ at1, es }
453+
(select (if b then (Some ts) else None) @@ at1) :: es }
461454

462-
select_instr_results_instr :
463-
| LPAR RESULT value_type_list RPAR select_instr_results_instr
455+
select_instr_results_instr_list :
456+
| LPAR RESULT value_type_list RPAR select_instr_results_instr_list
464457
{ fun c -> let _, ts, es = $5 c in true, $3 @ ts, es }
465-
| instr
458+
| instr_list
466459
{ fun c -> false, [], $1 c }
467460

468461

469-
call_instr :
470-
| CALL_INDIRECT var call_instr_type
471-
{ let at = at () in fun c -> call_indirect ($2 c table) ($3 c) @@ at }
472-
| CALL_INDIRECT call_instr_type /* Sugar */
473-
{ let at = at () in fun c -> call_indirect (0l @@ at) ($2 c) @@ at }
474-
475-
call_instr_type :
476-
| type_use call_instr_params
477-
{ let at1 = ati 1 in
478-
fun c ->
479-
match $2 c with
480-
| FuncType ([], []) -> $1 c type_
481-
| ft -> inline_type_explicit c ($1 c type_) ft at1 }
482-
| call_instr_params
483-
{ let at = at () in fun c -> inline_type c ($1 c) at }
484-
485-
call_instr_params :
486-
| LPAR PARAM value_type_list RPAR call_instr_params
487-
{ fun c -> let FuncType (ts1, ts2) = $5 c in FuncType ($3 @ ts1, ts2) }
488-
| call_instr_results
489-
{ fun c -> FuncType ([], $1 c) }
490-
491-
call_instr_results :
492-
| LPAR RESULT value_type_list RPAR call_instr_results
493-
{ fun c -> $3 @ $5 c }
494-
| /* empty */
495-
{ fun c -> [] }
496-
497-
498-
call_instr_instr :
499-
| CALL_INDIRECT var call_instr_type_instr
462+
call_instr_instr_list :
463+
| CALL_INDIRECT var call_instr_type_instr_list
500464
{ let at1 = ati 1 in
501-
fun c -> let x, es = $3 c in call_indirect ($2 c table) x @@ at1, es }
502-
| CALL_INDIRECT call_instr_type_instr /* Sugar */
465+
fun c -> let x, es = $3 c in
466+
(call_indirect ($2 c table) x @@ at1) :: es }
467+
| CALL_INDIRECT call_instr_type_instr_list /* Sugar */
503468
{ let at1 = ati 1 in
504-
fun c -> let x, es = $2 c in call_indirect (0l @@ at1) x @@ at1, es }
469+
fun c -> let x, es = $2 c in
470+
(call_indirect (0l @@ at1) x @@ at1) :: es }
505471

506-
call_instr_type_instr :
507-
| type_use call_instr_params_instr
472+
call_instr_type_instr_list :
473+
| type_use call_instr_params_instr_list
508474
{ let at1 = ati 1 in
509475
fun c ->
510476
match $2 c with
511477
| FuncType ([], []), es -> $1 c type_, es
512478
| ft, es -> inline_type_explicit c ($1 c type_) ft at1, es }
513-
| call_instr_params_instr
479+
| call_instr_params_instr_list
514480
{ let at = at () in
515481
fun c -> let ft, es = $1 c in inline_type c ft at, es }
516482

517-
call_instr_params_instr :
518-
| LPAR PARAM value_type_list RPAR call_instr_params_instr
483+
call_instr_params_instr_list :
484+
| LPAR PARAM value_type_list RPAR call_instr_params_instr_list
519485
{ fun c ->
520486
let FuncType (ts1, ts2), es = $5 c in FuncType ($3 @ ts1, ts2), es }
521-
| call_instr_results_instr
487+
| call_instr_results_instr_list
522488
{ fun c -> let ts, es = $1 c in FuncType ([], ts), es }
523489

524-
call_instr_results_instr :
525-
| LPAR RESULT value_type_list RPAR call_instr_results_instr
490+
call_instr_results_instr_list :
491+
| LPAR RESULT value_type_list RPAR call_instr_results_instr_list
526492
{ fun c -> let ts, es = $5 c in $3 @ ts, es }
527-
| instr
493+
| instr_list
528494
{ fun c -> [], $1 c }
529495

530496

@@ -657,12 +623,6 @@ if_ :
657623
| LPAR THEN instr_list RPAR /* Sugar */
658624
{ fun c c' -> [], $3 c', [] }
659625

660-
instr_list :
661-
| /* empty */ { fun c -> [] }
662-
| select_instr { fun c -> [$1 c] }
663-
| call_instr { fun c -> [$1 c] }
664-
| instr instr_list { fun c -> $1 c @ $2 c }
665-
666626
expr_list :
667627
| /* empty */ { fun c -> [] }
668628
| expr expr_list { fun c -> $1 c @ $2 c }

test/core/call_indirect.wast

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,3 +1015,23 @@
10151015
(module (table funcref (elem 0 0)))
10161016
"unknown function"
10171017
)
1018+
1019+
1020+
1021+
1022+
;; Flat syntax
1023+
1024+
(module
1025+
(table 1 funcref)
1026+
(func unreachable call_indirect)
1027+
(func unreachable call_indirect nop)
1028+
(func unreachable call_indirect call_indirect)
1029+
(func unreachable call_indirect (call_indirect))
1030+
(func unreachable call_indirect call_indirect call_indirect)
1031+
(func unreachable call_indirect (result))
1032+
(func unreachable call_indirect (result) (result))
1033+
(func unreachable call_indirect (result) (result) call_indirect)
1034+
(func unreachable call_indirect (result) (result) call_indirect (result))
1035+
(func (result i32) unreachable call_indirect select)
1036+
(func (result i32) unreachable call_indirect select call_indirect)
1037+
)

test/core/select.wast

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,3 +512,20 @@
512512
"type mismatch"
513513
)
514514

515+
516+
;; Flat syntax
517+
518+
(module
519+
(table 1 funcref)
520+
(func (result i32) unreachable select)
521+
(func (result i32) unreachable select nop)
522+
(func (result i32) unreachable select (select))
523+
(func (result i32) unreachable select select)
524+
(func (result i32) unreachable select select select)
525+
(func (result i32) unreachable select (result i32))
526+
(func (result i32) unreachable select (result i32) (result))
527+
(func (result i32) unreachable select (result i32) (result) select)
528+
(func (result i32) unreachable select (result) (result i32) select (result i32))
529+
(func (result i32) unreachable select call_indirect)
530+
(func (result i32) unreachable select call_indirect select)
531+
)

0 commit comments

Comments
 (0)