@@ -925,111 +925,92 @@ class Driver {
925925 }
926926
927927 visitValueBlock (
928- id : BlockId ,
928+ blockId : BlockId ,
929929 loc : SourceLocation ,
930930 fallthrough : BlockId | null = null ,
931931 ) : { block : BlockId ; value : ReactiveValue ; place : Place ; id : InstructionId } {
932+ const block = this . cx . ir . blocks . get ( blockId ) ! ;
932933 // If we've reached the fallthrough block, stop recursing
933- if ( fallthrough !== null && id === fallthrough ) {
934- const block = this . cx . ir . blocks . get ( id ) ! ;
935- // The fallthrough block should have instructions that we extract the value from
936- return this . extractValueBlockResult ( block . instructions , id , loc ) ;
934+ if ( fallthrough !== null && blockId === fallthrough ) {
935+ CompilerError . invariant ( false , {
936+ reason : 'Did not expect to reach the fallthrough of a value block' ,
937+ description : `Reached bb${ blockId } , which is the fallthrough for this value block` ,
938+ loc,
939+ } ) ;
937940 }
938- const defaultBlock = this . cx . ir . blocks . get ( id ) ! ;
939- if ( defaultBlock . terminal . kind === 'branch' ) {
940- if ( defaultBlock . instructions . length === 0 ) {
941+ if ( block . terminal . kind === 'branch' ) {
942+ if ( block . instructions . length === 0 ) {
941943 return {
942- block : defaultBlock . id ,
943- place : defaultBlock . terminal . test ,
944+ block : block . id ,
945+ place : block . terminal . test ,
944946 value : {
945947 kind : 'LoadLocal' ,
946- place : defaultBlock . terminal . test ,
947- loc : defaultBlock . terminal . test . loc ,
948+ place : block . terminal . test ,
949+ loc : block . terminal . test . loc ,
948950 } ,
949- id : defaultBlock . terminal . id ,
951+ id : block . terminal . id ,
950952 } ;
951953 }
952- return this . extractValueBlockResult (
953- defaultBlock . instructions ,
954- defaultBlock . id ,
955- loc ,
956- ) ;
957- } else if ( defaultBlock . terminal . kind === 'goto' ) {
958- if ( defaultBlock . instructions . length === 0 ) {
959- /*
960- * Empty goto blocks just forward to the next block.
961- * Follow the goto to get the actual value.
962- */
963- return this . visitValueBlock (
964- defaultBlock . terminal . block ,
954+ return this . extractValueBlockResult ( block . instructions , block . id , loc ) ;
955+ } else if ( block . terminal . kind === 'goto' ) {
956+ if ( block . instructions . length === 0 ) {
957+ CompilerError . invariant ( false , {
958+ reason : 'Unexpected empty block with `goto` terminal' ,
959+ description : `Block bb${ block . id } is empty` ,
965960 loc,
966- fallthrough ,
967- ) ;
961+ } ) ;
968962 }
969- return this . extractValueBlockResult (
970- defaultBlock . instructions ,
971- defaultBlock . id ,
972- loc ,
973- ) ;
974- } else if ( defaultBlock . terminal . kind === 'maybe-throw' ) {
963+ return this . extractValueBlockResult ( block . instructions , block . id , loc ) ;
964+ } else if ( block . terminal . kind === 'maybe-throw' ) {
975965 /*
976966 * ReactiveFunction does not explicitly model maybe-throw semantics,
977- * so maybe-throw terminals in value blocks flatten away. We continue
978- * to the continuation block if it's still part of the value block.
979- * The fallthrough parameter tells us when to stop recursing.
967+ * so maybe-throw terminals in value blocks flatten away. In general
968+ * we recurse to the continuation block.
969+ *
970+ * However, if the last portion
971+ * of the value block is a potentially throwing expression, then the
972+ * value block could be of the form
973+ * ```
974+ * bb1:
975+ * ...StoreLocal for the value block...
976+ * maybe-throw continuation=bb2
977+ * bb2:
978+ * goto (exit the value block)
979+ * ```
980+ *
981+ * Ie what would have been a StoreLocal+goto is split up because of
982+ * the maybe-throw. We detect this case and return the value of the
983+ * current block as the result of the value block
980984 */
981- const continuationId = defaultBlock . terminal . continuation ;
982-
983- // If the continuation is the fallthrough, we've reached the end of the value block
984- if ( fallthrough !== null && continuationId === fallthrough ) {
985- const instructions = defaultBlock . instructions ;
986- CompilerError . invariant ( instructions . length !== 0 , {
987- reason : `Unexpected empty maybe-throw block at value block boundary` ,
988- description : null ,
989- loc : defaultBlock . terminal . loc ,
990- } ) ;
991- return this . extractValueBlockResult ( instructions , defaultBlock . id , loc ) ;
992- }
993-
985+ const continuationId = block . terminal . continuation ;
994986 const continuationBlock = this . cx . ir . blocks . get ( continuationId ) ! ;
995-
996- /*
997- * If the continuation block is empty with a non-maybe-throw terminal,
998- * extract the result from this block's instructions using the continuation
999- * block's ID so visitValueBlockTerminal can find the terminal.
1000- */
1001987 if (
1002988 continuationBlock . instructions . length === 0 &&
1003- continuationBlock . terminal . kind !== 'maybe-throw '
989+ continuationBlock . terminal . kind === 'goto '
1004990 ) {
1005991 return this . extractValueBlockResult (
1006- defaultBlock . instructions ,
992+ block . instructions ,
1007993 continuationBlock . id ,
1008994 loc ,
1009995 ) ;
1010996 }
1011997
1012- // Recurse to the continuation, passing through the fallthrough
1013998 const continuation = this . visitValueBlock (
1014999 continuationId ,
10151000 loc ,
10161001 fallthrough ,
10171002 ) ;
1018- return this . wrapWithSequence (
1019- defaultBlock . instructions ,
1020- continuation ,
1021- loc ,
1022- ) ;
1003+ return this . wrapWithSequence ( block . instructions , continuation , loc ) ;
10231004 } else {
10241005 /*
10251006 * The value block ended in a value terminal, recurse to get the value
10261007 * of that terminal and stitch them together in a sequence.
10271008 */
1028- const init = this . visitValueBlockTerminal ( defaultBlock . terminal ) ;
1009+ const init = this . visitValueBlockTerminal ( block . terminal ) ;
10291010 const final = this . visitValueBlock ( init . fallthrough , loc ) ;
10301011 return this . wrapWithSequence (
10311012 [
1032- ...defaultBlock . instructions ,
1013+ ...block . instructions ,
10331014 { id : init . id , loc, lvalue : init . place , value : init . value } ,
10341015 ] ,
10351016 final ,
0 commit comments