sources/flow.h (39 lines of code) (raw):
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "cql.h"
#include "sem.h"
// Pushes a normal context that unsets all improvements made within it when it
// is popped. This should be used in most cases.
#define FLOW_PUSH_CONTEXT_NORMAL() \
void *flow_context_normal; \
_flow_push_context_normal();
// Pops a normal context.
#define FLOW_POP_CONTEXT_NORMAL() \
(void)flow_context_normal; \
_flow_pop_context_normal();
// Pushes a branch group context for an IF, CASE, et cetera.
#define FLOW_PUSH_CONTEXT_BRANCH_GROUP() \
void *flow_context_branch_group; \
_flow_push_context_branch_group();
// Pops a branch group context.
#define FLOW_POP_CONTEXT_BRANCH_GROUP() \
(void)flow_context_branch_group; \
_flow_pop_context_branch_group();
// Pushes a branch context. This must only be used within a branch group context
// and must be used for all branches within it. (For empty branches with no
// statements, one may use `flow_context_branch_group_add_empty_branch` instead
// of pushing and immediately popping a new branch context.)
#define FLOW_PUSH_CONTEXT_BRANCH() \
void *flow_context_branch; \
_flow_push_context_branch();
// Pops a branch context.
#define FLOW_POP_CONTEXT_BRANCH() \
(void)flow_context_branch; \
_flow_pop_context_branch();
// Pushes a jump context. This should be used for statement lists where control
// flow can jump to the end of the context (e.g., TRY via THROW (or a CALL
// containing a THROW), WHILE and LOOP via CONTINUE and LEAVE, et cetera). It
// should not be used for statement lists merely because of the possibility of
// an early RETURN: Jump contexts are specifically designed to safely manage
// the setting and unsetting of improvements *within* a procedure.
#define FLOW_PUSH_CONTEXT_JUMP() \
void *flow_context_jump; \
_flow_push_context_jump();
// Pops a jump context.
#define FLOW_POP_CONTEXT_JUMP() \
(void)flow_context_jump; \
_flow_pop_context_jump();
// Sets `flag` on `*type`. This must not be called if the flag is already set or
// if a flow context is not in effect.
cql_noexport void flow_set_flag_for_type(sem_t flag, sem_t *type);
// Un-sets `flag` on `*type`. This must not be called unless the flag is already
// set or if a flow context is not in effect.
cql_noexport void flow_unset_flag_for_type(sem_t flag, sem_t *type);
// Indicates that the current branch group context will (or does) contain a
// catch-all branch or otherwise covers all possible cases. This must only be
// called while the current flow context is a branch group context. If this is
// not called, it will be assumed that all cases are not covered.
cql_noexport void flow_set_context_branch_group_covers_all_cases(bool_t covers_all_cases);
// Adds an empty branch to the current branch group context. It is equivalent to
// `FLOW_PUSH_CONTEXT_BRANCH` immediately followed by `FLOW_POP_CONTEXT_BRANCH`
// and exists only for the sake of convenience.
cql_noexport void flow_context_branch_group_add_empty_branch();
// Records the fact that the current context *always* jumps until the end of the
// nearest enclosing jump context (if any) or any statement thereafter. If this
// is called when no jump context is in effect, it is assumed that the jump is
// to a statement beyond all current contexts (as is the case with a RETURN, or
// with a THROW with no enclosing TRY block).
//
// This function can be used in any context, but it only has an effect when the
// current context is a branch context. When the current context is a branch
// context, recording the fact that the branch always jumps may allow additional
// improvements to persist after the end of the enclosing branch group.
cql_noexport void flow_set_context_always_jumps(bool_t always_jumps);
cql_noexport void _flow_push_context_normal();
cql_noexport void _flow_pop_context_normal();
cql_noexport void _flow_push_context_branch_group();
cql_noexport void _flow_pop_context_branch_group();
cql_noexport void _flow_push_context_branch();
cql_noexport void _flow_pop_context_branch();
cql_noexport void _flow_push_context_jump();
cql_noexport void _flow_pop_context_jump();