Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

rethrow's immediate arguments #74

Closed
@aheejin

Description

@aheejin

In the current spec, rethrow does not take any immediate argument, and only pops except_ref from the top of stack and rethrows it.

I'm planning to add two immediate arguments to rethrow. These two are not new; they have been discussed previously.

Depths to break out of

Branches can break out of arbitrary number of blocks and loops thanks to their immediate depth argument, but rethrow currently does not have it. So I am planning to add a depth immediate argument to rethrow, which was first proposed in #29 (comment).

One thing we should consider is, depth calculation should be slightly different from that of branches. I'd like to make the depth calculation for rethrow the same as that of branches, but for branches, the depth is increased at block start instructions (block, loop, and try) and is decreased at block end instruction (end), whereas for rethrows, the depth should be decreased not at block end instruction (end) but at catch instruction. For example,

try
  try
    br 0       // branches to (2)
    rethrow 0  // rethrows to (1)
  catch        <-- (1)
    br 0       // branches to (2)
    rethrow 0  // rethrows to (3)
  end
  ...          <-- (2)
catch          <-- (3)
end

Here two br instructions are within the same try~end scope, so they branch to the same place. But two rethrow instructions rethrow to different places, because the level is decreased not at end but at catch.

To resolve this, the current LLVM toolchain implemenation maintains separate EH stack for rethrow depth calculation, in the way that EH stack depth is only incremented with try and decremented with catch and does not count other blocks or loops. As in the example below, rethrow does not count all blocks when computing depth.

try                                                                              
  block                                                                          
    block                                                                        
      block                                                                      
        block                                                                    
          try                                                                    
            rethrow 0  // rethrows to (1)                                        
            rethrow 1  // rethrows to (2)                                        
          catch        <-- (1)                                                   
          end                                                                    
        end                                                                      
      end                                                                        
    end                                                                          
  end                                                                            
catch                                                                            
end                    <-- (2)

@mstarzinger and I discussed how to compute rethrow's depth argument over email chain a little, and I'm also not sure if we settled on a conclusion.

Which exception to rethrow

The first version of EH proposal had an immediate argument to specify which exceptions on the stack to rethrow. So

try
  ...
catch 1
  ...
  block
    ...
    try
      ...
    catch 2
      ...
      try
        ...
      catch 3
        ...
        rethrow N
      end
    end
  end
  ...
end

In this example, N is used to disambiguate which caught exception is being rethrown. It could rethrow any of the three caught exceptions. Hence, rethrow 0 corresponds to the exception caught by catch 3, rethrow 1 corresponds to the exception caught by catch 2, and rethrow 3 corresponds to the exception caught by catch 1.

I don't see any use cases of this in C++, but I recall @rossberg suggested to keep this for other languages. Is that right?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions