You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Aug 2, 2019. It is now read-only.
In addition to BRANCH, BRANCH2, SWITCH, TAILCALL, RET, THROW, and all instructions that have an exception clause (EXC(%nor %exc)), I found two other instructions may end a basic block, too.
The @uvm.thread_exit "common instruction": It immediately stops a thread and kills its stack, so it can never continue.
The SWAPSTACK is a bit complicated. It is a terminator iff:
a. it has an EXC(%xxx %yyy) clause: because the control flow diverges; or
b. it kills the old stack: the old stack is killed, so it can never return. This case usually occurs in coroutines. (This case is not yet mentioned in the spec, but I should mention it.)
Example:
.funcdef @some_coroutine ....... {
%entry(<@stackref> %main):
// yield some data
// and then end itself
%stop_iteration = NEW <@StopIteration>
SWAPSTACK %main KILL_OLD THROW_EXC %stop_iteration
// unreachable here.
}
So I suggest not make terminator instructions (or exit instructions) a separate data type (LLVM does make them a separate type), but make "is an exit instruction" a property of instructions. Then the body of a basic block is "a list of instructions which are not exits", and the exit is "an instruction which is an exit".
Exit instructions can return values, too. CALL is an example. If it can catch exceptions (has EXC(%nor %exc)), it diverges, but the return value can be used by its normal destination, though not the exceptional destination. Having a unified "exit" and "non-exit" instruction type which always return values (may be void) can model this case.
In LLVM, there are call and invoke, both calls functions. The main difference is whether there are the nor, exc destinations. But I think if two instructions do the same thing except handling exceptions differently, they shouldn't be two. They should be one instruction and only annotate the difference with a clause.
The text was updated successfully, but these errors were encountered:
Sign up for freeto subscribe to this conversation on GitHub.
Already have an account?
Sign in.
In addition to BRANCH, BRANCH2, SWITCH, TAILCALL, RET, THROW, and all instructions that have an exception clause (
EXC(%nor %exc)
), I found two other instructions may end a basic block, too.@uvm.thread_exit
"common instruction": It immediately stops a thread and kills its stack, so it can never continue.SWAPSTACK
is a bit complicated. It is a terminator iff:a. it has an
EXC(%xxx %yyy)
clause: because the control flow diverges; orb. it kills the old stack: the old stack is killed, so it can never return. This case usually occurs in coroutines. (This case is not yet mentioned in the spec, but I should mention it.)
Example:
So I suggest not make terminator instructions (or exit instructions) a separate data type (LLVM does make them a separate type), but make "is an exit instruction" a property of instructions. Then the body of a basic block is "a list of instructions which are not exits", and the exit is "an instruction which is an exit".
Exit instructions can return values, too.
CALL
is an example. If it can catch exceptions (hasEXC(%nor %exc)
), it diverges, but the return value can be used by its normal destination, though not the exceptional destination. Having a unified "exit" and "non-exit" instruction type which always return values (may bevoid
) can model this case.In LLVM, there are
call
andinvoke
, both calls functions. The main difference is whether there are thenor, exc
destinations. But I think if two instructions do the same thing except handling exceptions differently, they shouldn't be two. They should be one instruction and only annotate the difference with a clause.The text was updated successfully, but these errors were encountered: