|
8 | 8 | #define FORTH_OPS |
9 | 9 |
|
10 | 10 | include "warpforth/Dialect/Forth/ForthDialect.td" |
11 | | -include "mlir/Interfaces/ControlFlowInterfaces.td" |
12 | 11 | include "mlir/Interfaces/SideEffectInterfaces.td" |
13 | 12 |
|
14 | 13 | //===----------------------------------------------------------------------===// |
@@ -446,102 +445,48 @@ def Forth_ZeroEqOp : Forth_StackOpBase<"zero_eq"> { |
446 | 445 | } |
447 | 446 |
|
448 | 447 | //===----------------------------------------------------------------------===// |
449 | | -// Control flow operations. |
| 448 | +// Control flow support operations. |
450 | 449 | //===----------------------------------------------------------------------===// |
451 | 450 |
|
452 | | -def Forth_YieldOp : Forth_Op<"yield", [Pure, Terminator, ReturnLike, |
453 | | - ParentOneOf<["IfOp", "BeginUntilOp", "BeginWhileRepeatOp", "DoLoopOp"]>]> { |
454 | | - let summary = "Yield stack from control flow region"; |
| 451 | +def Forth_PopFlagOp : Forth_Op<"pop_flag", [Pure]> { |
| 452 | + let summary = "Pop top of stack as boolean flag"; |
455 | 453 | let description = [{ |
456 | | - Yields the current stack state from a control flow region back to |
457 | | - the parent operation. Acts as a region terminator. |
458 | | - When the optional `while_cond` attribute is present, the yield acts as |
459 | | - a WHILE condition (continue when flag is non-zero) rather than |
460 | | - UNTIL (exit when flag is non-zero). |
| 454 | + Pops the top value from the stack and returns it as an i1 flag |
| 455 | + (non-zero = true, zero = false). Used by IF, UNTIL, WHILE. |
| 456 | + Forth semantics: ( flag -- ) |
461 | 457 | }]; |
462 | | - let arguments = (ins Forth_StackType:$result, OptionalAttr<UnitAttr>:$while_cond); |
| 458 | + let arguments = (ins Forth_StackType:$input_stack); |
| 459 | + let results = (outs Forth_StackType:$output_stack, I1:$flag); |
463 | 460 | let assemblyFormat = [{ |
464 | | - $result (`while_cond` $while_cond^)? attr-dict `:` type($result) |
| 461 | + $input_stack attr-dict `:` type($input_stack) `->` type($output_stack) `,` type($flag) |
465 | 462 | }]; |
466 | 463 | } |
467 | 464 |
|
468 | | -def Forth_IfOp : Forth_Op<"if", [RecursiveMemoryEffects, |
469 | | - DeclareOpInterfaceMethods<RegionBranchOpInterface, |
470 | | - ["getEntrySuccessorOperands"]>]> { |
471 | | - let summary = "Conditional execution"; |
| 465 | +def Forth_PopOp : Forth_Op<"pop", [Pure]> { |
| 466 | + let summary = "Pop top of stack as i64 value"; |
472 | 467 | let description = [{ |
473 | | - Conditional execution. If the flag is non-zero, the then region executes; |
474 | | - otherwise the else region executes. Each region must yield the resulting |
475 | | - stack. |
476 | | - Forth semantics: flag IF then-body ELSE else-body THEN |
| 468 | + Pops the top value from the stack and returns it as an i64. |
| 469 | + Used by DO to pop start and limit. |
| 470 | + Forth semantics: ( x -- ) |
477 | 471 | }]; |
478 | 472 | let arguments = (ins Forth_StackType:$input_stack); |
479 | | - let results = (outs Forth_StackType:$output_stack); |
480 | | - let regions = (region SizedRegion<1>:$then_region, |
481 | | - SizedRegion<1>:$else_region); |
482 | | - let hasCustomAssemblyFormat = 1; |
483 | | -} |
484 | | - |
485 | | -def Forth_BeginUntilOp : Forth_Op<"begin_until", [RecursiveMemoryEffects, |
486 | | - DeclareOpInterfaceMethods<RegionBranchOpInterface, |
487 | | - ["getEntrySuccessorOperands"]>]> { |
488 | | - let summary = "Post-test loop (do-while)"; |
489 | | - let description = [{ |
490 | | - BEGIN/UNTIL loop. Executes body, pops flag. If flag is zero, loops back. |
491 | | - If non-zero, exits. Stack effect: ( -- ) with flag consumed each iteration. |
492 | | - }]; |
493 | | - let arguments = (ins Forth_StackType:$input_stack); |
494 | | - let results = (outs Forth_StackType:$output_stack); |
495 | | - let regions = (region SizedRegion<1>:$body_region); |
496 | | - let hasCustomAssemblyFormat = 1; |
497 | | -} |
498 | | - |
499 | | -def Forth_DoLoopOp : Forth_Op<"do_loop", [RecursiveMemoryEffects, |
500 | | - DeclareOpInterfaceMethods<RegionBranchOpInterface, |
501 | | - ["getEntrySuccessorOperands"]>]> { |
502 | | - let summary = "Counted loop (DO/LOOP)"; |
503 | | - let description = [{ |
504 | | - Pops start and limit from the stack, iterates from start to limit-1. |
505 | | - Use forth.loop_index (I word) inside to access the current loop index. |
506 | | - Stack effect: ( limit start -- ) |
507 | | - }]; |
508 | | - let arguments = (ins Forth_StackType:$input_stack); |
509 | | - let results = (outs Forth_StackType:$output_stack); |
510 | | - let regions = (region SizedRegion<1>:$body_region); |
511 | | - let hasCustomAssemblyFormat = 1; |
512 | | -} |
513 | | - |
514 | | -def Forth_BeginWhileRepeatOp : Forth_Op<"begin_while_repeat", |
515 | | - [RecursiveMemoryEffects, |
516 | | - DeclareOpInterfaceMethods<RegionBranchOpInterface, |
517 | | - ["getEntrySuccessorOperands"]>]> { |
518 | | - let summary = "Pre-test loop (BEGIN/WHILE/REPEAT)"; |
519 | | - let description = [{ |
520 | | - BEGIN/WHILE/REPEAT loop. The condition region runs first, WHILE pops flag. |
521 | | - If flag is non-zero, the body region executes and loops back to condition. |
522 | | - If flag is zero, the loop exits. |
523 | | - Stack effect: ( -- ) with flag consumed each iteration. |
| 473 | + let results = (outs Forth_StackType:$output_stack, I64:$value); |
| 474 | + let assemblyFormat = [{ |
| 475 | + $input_stack attr-dict `:` type($input_stack) `->` type($output_stack) `,` type($value) |
524 | 476 | }]; |
525 | | - let arguments = (ins Forth_StackType:$input_stack); |
526 | | - let results = (outs Forth_StackType:$output_stack); |
527 | | - let regions = (region SizedRegion<1>:$condition_region, |
528 | | - SizedRegion<1>:$body_region); |
529 | | - let hasCustomAssemblyFormat = 1; |
530 | 477 | } |
531 | 478 |
|
532 | | -def Forth_LoopIndexOp : Forth_Op<"loop_index", [Pure]> { |
533 | | - let summary = "Push loop index onto stack (I/J/K words)"; |
| 479 | +def Forth_PushValueOp : Forth_Op<"push_value", [Pure]> { |
| 480 | + let summary = "Push dynamic i64 value onto stack"; |
534 | 481 | let description = [{ |
535 | | - Pushes the loop index at the given nesting depth onto the stack. |
536 | | - depth=0 is I (innermost), depth=1 is J, depth=2 is K. |
537 | | - Only valid inside nested forth.do_loop bodies at sufficient depth. |
538 | | - ( -- index ) |
| 482 | + Pushes a dynamic i64 value onto the stack. Used by I/J/K to push |
| 483 | + the loop counter value. |
| 484 | + Forth semantics: ( -- x ) |
539 | 485 | }]; |
540 | | - let arguments = (ins Forth_StackType:$input_stack, |
541 | | - DefaultValuedAttr<I64Attr, "0">:$depth); |
| 486 | + let arguments = (ins Forth_StackType:$input_stack, I64:$value); |
542 | 487 | let results = (outs Forth_StackType:$output_stack); |
543 | 488 | let assemblyFormat = [{ |
544 | | - $input_stack attr-dict `:` type($input_stack) `->` type($output_stack) |
| 489 | + $input_stack `,` $value attr-dict `:` type($input_stack) `,` type($value) `->` type($output_stack) |
545 | 490 | }]; |
546 | 491 | } |
547 | 492 |
|
|
0 commit comments