Example #1
0
 def is_blob(self, allow_handle=False):
     """
     Check if self is a blob type.
     A blob is a type that can be treated as a sequence of bytes without any semantics.
     This implies that no elements within the blob need to be translated in any way
     during command processing.
     :param allow_handle: If True, allow handles inside the blob.
     :return: True, iff self is a blob.
     """
     individual_field_preds = [
         t.is_blob(allow_handle) for t in self.fields.values()
     ]
     fields_pred = reduce(lambda a, b: Expr(a) & b, individual_field_preds,
                          True)
     allowed = {
         "NW_OPAQUE", "NW_CALLBACK", "NW_CALLBACK",
         "NW_CALLBACK_REGISTRATION"
     } | ({"NW_HANDLE"} if allow_handle else set())
     transfer_pred = Expr(self.transfer).one_of(allowed)
     pointee_pred = True
     if isinstance(self, StaticArray):
         pointee_pred = self.pointee.is_blob(allow_handle) & Expr(
             self.buffer_allocator == "malloc")
     pred = transfer_pred & fields_pred & pointee_pred
     if "ava_index" in str(
             pred
     ):  # TODO: Remove this hack by tracking the usage of variables in expressions.
         return Expr(False)
     return pred
Example #2
0
def compute_buffer_size(type: Type, original_type: Optional[Type] = None):
    size_expr = Expr(type.buffer)
    if original_type and original_type.pointee.spelling != type.pointee.spelling:
        size_adjustment = f" * sizeof({original_type.pointee.spelling}) / sizeof({type.pointee.spelling})"
    else:
        size_adjustment = ""
    return Expr(f"(size_t){size_expr.group()}{size_adjustment}").group()
Example #3
0
 def default_case():
     return (Expr(type.transfer).equals("NW_HANDLE")).if_then_else(
         Expr(not type.deallocates).if_then_else(
             assign_record_replay_functions(param_value, type).then(
                 record_call_metadata(param_value, type)),
             expunge_calls(param_value, type),
         ))
Example #4
0
File: caller.py Project: yuhc/ava
        def buffer_case():
            if not hasattr(type_, "pointee"):
                return """abort_with_reason("Reached code to handle buffer in non-pointer type.");"""
            if not arg.input:
                return simple_buffer_case()

            tmp_name = f"__tmp_{arg.name}_{depth}"
            size_name = f"__size_{arg.name}_{depth}"
            loop = for_all_elements(
                (arg_value, tmp_name),
                cmd_value_type,
                type_,
                depth=depth,
                argument=argument,
                precomputed_size=size_name,
                original_type=original_type,
                **other,
            )
            return (Expr(arg_value).not_equals("NULL") & (Expr(type_.buffer) > 0)).if_then_else(
                f"""
                    {allocate_tmp_buffer(
                        tmp_name,
                        size_name,
                        type_,
                        alloc_list=alloc_list,
                        original_type=original_type
                    )}
                    {loop}
                    {attach_data(tmp_name)}
                """,
                f"{cmd_value} = NULL;",
            )
Example #5
0
 def default_case():
     dealloc_code = (Expr(type.transfer).equals("NW_HANDLE") & type.deallocates).if_then_else(
         f"""
         ava_coupled_free(&__ava_endpoint, {local_value});
         """.strip()
     )
     return dealloc_code.then((Expr(arg.output) | arg.ret).if_then_else(f"{param_value} = {local_value};"))
Example #6
0
def get_transfer_buffer_expr(value: str,
                             type_: Type,
                             *,
                             not_null=False) -> ExprOrStr:
    """
    Generate an expression that gets the transfer buffer of `value` (which has `type`).
    :param value: The value whose transfer buffer to get.
    :param type: The type of value.
    :param not_null: If True, then this function does not generate NULL checks.
    :return: A C expression.
    """
    return (Expr(value).not_equals("NULL") | not_null).if_then_else_expression(
        Expr(type_.transfer).equals("NW_BUFFER").if_then_else_expression(
            f"({type_.spelling})command_channel_get_buffer(__chan, __cmd, {value})",
            Expr(type_.transfer).equals("NW_ZEROCOPY_BUFFER").
            if_then_else_expression(
                # TODO(yuhc): Add back zero copy region supprot after this feature is refactored.
                # pylint: disable=line-too-long
                # f"({type_.spelling})ava_zcopy_region_decode_position_independent(__ava_endpoint.zcopy_region, {value})",
                f"({type_.spelling})command_channel_get_buffer(__chan, __cmd, {value})",
                f"({type_.spelling}){value}",
            ),
        ),
        f"({type_.spelling}){value}",
    )
Example #7
0
File: caller.py Project: yuhc/ava
 def get_buffer_code():
     nonlocal reported_missing_lifetime
     if not reported_missing_lifetime:
         if ((arg.ret or arg.output and depth > 0) and type_.buffer) and type_.lifetime == "AVA_CALL":
             reported_missing_lifetime = True
             generate_expects(
                 False,
                 "Returned buffers with call lifetime are almost always incorrect. "
                 "(You may want to set a lifetime.)",
             )
     return Expr(
         f"""
         {DECLARE_BUFFER_SIZE_EXPR}
         {type_.attach_to(src_name)};
         {src_name} = ({type_.spelling})({get_transfer_buffer_expr(local_value, type_, not_null=True)});
         """
     ).then(
         Expr(type_.lifetime)
         .not_equals("AVA_CALL")
         .if_then_else(
             f"""{get_buffer(
                     param_value,
                     cast_type,
                     local_value,
                     type_,
                     original_type=original_type,
                     not_null=True,
                     declare_buffer_size=False
                 )}""",
             f"""__buffer_size = {compute_buffer_size(type_, original_type)};""",
         )
         .then(Expr(arg.output).if_then_else(f"AVA_DEBUG_ASSERT({param_value} != NULL);"))
     )
Example #8
0
    def convert_result_value(values,
                             type: Type,
                             depth,
                             original_type=None,
                             **other) -> str:
        if isinstance(type, ConditionalType):
            return Expr(type.predicate).if_then_else(
                convert_result_value(values,
                                     type.then_type,
                                     depth,
                                     original_type=type.original_type,
                                     **other),
                convert_result_value(values,
                                     type.else_type,
                                     depth,
                                     original_type=type.original_type,
                                     **other))

        if type.is_void:
            return """abort_with_reason("Reached code to handle void value.");"""

        original_value, local_value = values
        buffer_pred = (Expr(type.transfer).equals("NW_BUFFER")
                       & Expr(local_value).not_equals("NULL") &
                       (Expr(type.buffer) > 0))

        def simple_buffer_case():
            return ""

        def buffer_case():
            if not hasattr(type, "pointee"):
                return """abort_with_reason("Reached code to handle buffer in non-pointer type.");"""
            tmp_name = f"__tmp_{arg.name}_{depth}"
            inner_values = (tmp_name, local_value)
            return buffer_pred.if_then_else(f"""
                {type.nonconst.attach_to(tmp_name)}; 
                {get_buffer(tmp_name, original_value, type, original_type=original_type)}
                {for_all_elements(inner_values, type, depth=depth, original_type=original_type, **other)}
                """)

        def default_case():
            return Expr(type.transfer).equals("NW_HANDLE").if_then_else((
                ~Expr(type.deallocates)
            ).if_then_else(
                f"nw_handle_pool_assign_handle(handle_pool, (void*){original_value}, (void*){local_value});"
            ), ((Expr(arg.ret) | Expr(type.transfer).equals("NW_OPAQUE"))
                & Expr(not isinstance(type, FunctionPointer))
                ).if_then_else(f"assert({original_value} == {local_value});"))

        if type.fields:
            return for_all_elements(values,
                                    type,
                                    depth=depth,
                                    original_type=original_type,
                                    **other)
        return type.is_simple_buffer().if_then_else(
            simple_buffer_case,
            Expr(type.transfer).equals("NW_BUFFER").if_then_else(
                buffer_case, default_case)).scope()
Example #9
0
 def default_case():
     return Expr(type.transfer).equals("NW_HANDLE").if_then_else((
         ~Expr(type.deallocates)
     ).if_then_else(
         f"nw_handle_pool_assign_handle(handle_pool, (void*){original_value}, (void*){local_value});"
     ), ((Expr(arg.ret) | Expr(type.transfer).equals("NW_OPAQUE"))
         & Expr(not isinstance(type, FunctionPointer))
         ).if_then_else(f"assert({original_value} == {local_value});"))
Example #10
0
 def default_case():
     handlepool_function = "nw_handle_pool_lookup_or_insert"
     return Expr(type.transfer).equals("NW_HANDLE").if_then_else(
         Expr(type.deallocates).if_then_else(
             f"{param_value} = NULL;",
             f"{param_value} = ({type.nonconst.spelling}){handlepool_function}(handle_pool, (void*){local_value});"
         ),
         Expr(not type.is_void).if_then_else(
             f"{param_value} = {local_value};"))
Example #11
0
    def convert_result_value(values,
                             type: Type,
                             depth,
                             original_type=None,
                             **other):
        if isinstance(type, ConditionalType):
            return Expr(type.predicate).if_then_else(
                convert_result_value(values,
                                     type.then_type,
                                     depth,
                                     original_type=type.original_type,
                                     **other),
                convert_result_value(values,
                                     type.else_type,
                                     depth,
                                     original_type=type.original_type,
                                     **other))

        local_value, = values
        buffer_pred = (Expr(type.transfer).equals("NW_BUFFER")
                       & f"{local_value} != NULL")
        dealloc_shadows = Expr(type.deallocates).if_then_else(
            f"ava_shadow_buffer_free_coupled(&__ava_endpoint, (void *){local_value});"
        )

        def simple_buffer_case():
            return ""

        def buffer_case():
            if not hasattr(type, "pointee"):
                return """abort_with_reason("Reached code to handle buffer in non-pointer type.");"""
            return buffer_pred.if_then_else(
                for_all_elements(values,
                                 type,
                                 depth=depth,
                                 original_type=original_type,
                                 **other))

        def default_case():
            dealloc_code = Expr(type.deallocates).if_then_else(
                Expr(type.transfer).equals("NW_HANDLE").if_then_else(f"""
                    ava_coupled_free(&__ava_endpoint, {local_value});
                    """.strip()))
            return dealloc_code

        if type.fields:
            return for_all_elements(values,
                                    type,
                                    depth=depth,
                                    original_type=original_type,
                                    **other)
        return type.is_simple_buffer(allow_handle=False).if_then_else(
            simple_buffer_case,
            Expr(type.transfer).equals("NW_BUFFER").if_then_else(
                buffer_case, (Expr(type.transfer).one_of({
                    "NW_OPAQUE", "NW_HANDLE"
                })).if_then_else(default_case))).then(dealloc_shadows).scope()
Example #12
0
 def deref_code(handlepool_function: str) -> callable:
     return lambda: (Expr(type.transfer).one_of({
         "NW_CALLBACK", "NW_CALLBACK_REGISTRATION"
     })).if_then_else(
         f"{local_value} =  ({param_value} == NULL) ? NULL : {type.callback_stub_function};",
         (Expr(type.transfer).equals("NW_HANDLE")).if_then_else(
             f"{local_value} = ({type.nonconst.spelling}){handlepool_function}(handle_pool, (void*){param_value});",
             Expr(not type.is_void).if_then_else(
                 f"{local_value} = {param_value};",
                 """abort_with_reason("Reached code to handle void value.");"""
             )))
Example #13
0
def compute_buffer_size(type: Type, original_type: Optional[Type] = None):
    size_expr = Expr(type.buffer)
    if original_type and original_type.pointee.spelling != type.pointee.spelling:
        pointee_size = f"sizeof({type.pointee.spelling})"
        # for void* buffer, assume that each element is 1 byte
        if type.pointee.is_void:
            pointee_size = "1"
        size_adjustment = f" * sizeof({original_type.pointee.spelling}) / {pointee_size}"
    else:
        size_adjustment = ""
    return Expr(f"(size_t){size_expr.group()}{size_adjustment}").group()
Example #14
0
def get_buffer(
    target: str,
    target_type: Type,
    value: str,
    type_: Type,
    *,
    original_type: Optional[Type],
    precomputed_size=None,
    not_null=False,
    declare_buffer_size=True,
) -> Expr:
    """
    Generate code that sets target to the local buffer to use for value.
    After this code executes `__buffer_size` is equal to the buffer size in elements.
    :param target: The variable in which to store the buffer pointer.
    :param value: The original value to translate.
    :param type_: The type of value.
    :param original_type: The original type if type is immediately inside a ConditionalType.
    :param precomputed_size: The expression for a precomputed size of value in *elements*.
    :param not_null: If True, then this function does not generate NULL checks.
    :return: A series of C statements.
    """
    size_expr = compute_buffer_size(
        type_, original_type) if precomputed_size is None else precomputed_size
    declarations = DECLARE_BUFFER_SIZE_EXPR if declare_buffer_size else Expr(
        "")

    pointee_size = f"sizeof({type_.pointee.spelling})"
    # for void* buffer, assume that each element is 1 byte
    if type_.pointee.is_void:
        pointee_size = "1"

    return declarations.then((
        type_.lifetime.not_equals("AVA_CALL") &
        (Expr(value).not_equals("NULL") | not_null)
    ).if_then_else(
        # FIXME: The initial assert is probably incorrect. Should it be checking the ADDRESSES?
        #   Should it be there at all? Commented for now: AVA_DEBUG_ASSERT({target} != {value});
        #   (was at top of code)
        # FIXME: Should we check the buffer size? Can it be computed here?
        #   AVA_DEBUG_ASSERT(__buffer_size == {size_expr}); (was at bottom of code)
        f"""
            /* Size is in bytes until the division below. */
            {target} = ({target_type})({get_buffer_expr(value, type_, not_null=not_null, size_out="__buffer_size")});
            AVA_DEBUG_ASSERT(__buffer_size % {pointee_size} == 0);
            __buffer_size /= {pointee_size};
            /* Size is now in elements. */
        """.lstrip(),
        f"""
            __buffer_size = {size_expr};
            {target} = ({target_type})({get_buffer_expr(value, type_, not_null=not_null, size_out="__buffer_size")});
        """.strip(),
    ))
Example #15
0
def attach_buffer(target,
                  value,
                  data,
                  type: Type,
                  copy: Union[Expr, Any],
                  *,
                  cmd,
                  original_type: Optional[Type],
                  expect_reply: bool,
                  precomputed_size=None):
    """
    Generate code to attach a buffer to a command.

    :param target: The value to set to the buffer offset after attaching.
    :param value: The value to attach.
    :param type: The type of value.
    :param copy: An expression which is true if if this value should be copied.
    :param cmd: The command to attach to.
    :param original_type: The original type if type is immediately inside a ConditionalType.
    :param precomputed_size: The expression for a precomputed size of value in *elements*.
    :return: A series of C statements.
    """
    cmd = f"(struct command_base*){cmd}"
    size_expr = size_to_bytes(
        compute_buffer_size(type, original_type)
        if precomputed_size is None else precomputed_size, type)

    def simple_attach(func):
        return lambda: f"""{target} = ({type.nonconst.spelling}){func}(__chan, {cmd}, {data}, {size_expr});
                        """

    def zerocopy_attach(func="ava_zcopy_region_encode_position_independent"):
        return lambda: f"""{target} = ({type.nonconst.spelling}){func}(__ava_endpoint.zcopy_region, {data});
                        """

    def shadow_attach(func):
        return lambda: f"""{target} = ({type.nonconst.spelling}){func}(&__ava_endpoint,
                        __chan, {cmd}, {value}, {data}, {size_expr},
                        {type.lifetime}, {type.buffer_allocator}, {type.buffer_deallocator},
                        alloca(sizeof(struct ava_buffer_header_t)));"""

    return type.transfer.equals("NW_ZEROCOPY_BUFFER").if_then_else(
        zerocopy_attach(),
        type.lifetime.equals("AVA_CALL").if_then_else(
            Expr(copy).if_then_else(
                simple_attach("command_channel_attach_buffer"),
                f"{target} = HAS_OUT_BUFFER_SENTINEL;"
                if expect_reply else f"{target} = NULL; /* No output */\n"),
            Expr(copy).if_then_else(
                shadow_attach("ava_shadow_buffer_attach_buffer"),
                shadow_attach("ava_shadow_buffer_attach_buffer_without_data"),
            )))
Example #16
0
 def default_case():
     handlepool_function = "nw_handle_pool_lookup_or_insert"
     return (
         Expr(type_.transfer)
         .equals("NW_HANDLE")
         .if_then_else(
             Expr(type_.deallocates).if_then_else(
                 f"{param_value} = NULL;",
                 f"{param_value} = ({cast_type})({handlepool_function}(handle_pool, (void*){local_value}));",
             ),
             Expr(not type_.is_void).if_then_else(f"{param_value} = {local_value};"),
         )
     )
Example #17
0
    def copy_for_value(values, type: Type, depth, argument, original_type=None, **other):
        if isinstance(type, ConditionalType):
            return Expr(type.predicate).if_then_else(
                copy_for_value(values, type.then_type, depth, argument, original_type=type.original_type, **other),
                copy_for_value(values, type.else_type, depth, argument, original_type=type.original_type, **other))

        arg_value, cmd_value = values

        def attach_data(data):
            return attach_buffer(cmd_value, arg_value, data, type, arg.input, cmd=dest, original_type=original_type, expect_reply=True)

        def simple_buffer_case():
            if not hasattr(type, "pointee"):
                return """abort_with_reason("Reached code to handle buffer in non-pointer type.");"""
            return (Expr(arg_value).not_equals("NULL") & (Expr(type.buffer) > 0)).if_then_else(
                attach_data(arg_value),
                f"{cmd_value} = NULL;")

        def buffer_case():
            if not hasattr(type, "pointee"):
                return """abort_with_reason("Reached code to handle buffer in non-pointer type.");"""
            if not arg.input:
                return simple_buffer_case()

            tmp_name = f"__tmp_{arg.name}_{depth}"
            size_name = f"__size_{arg.name}_{depth}"
            loop = for_all_elements((arg_value, tmp_name), type, depth=depth, argument=argument,
                                    precomputed_size=size_name, original_type=original_type, **other)
            return (Expr(arg_value).not_equals("NULL") & (Expr(type.buffer) > 0)).if_then_else(
                f"""
                    {allocate_tmp_buffer(tmp_name, size_name, type, alloc_list=alloc_list, original_type=original_type)}
                    {loop}
                    {attach_data(tmp_name)}
                """,
                f"{cmd_value} = NULL;"
            )

        def default_case():
            return Expr(not type.is_void).if_then_else(
                f"{cmd_value} = {arg_value};",
                """abort_with_reason("Reached code to handle void value.");""")

        if type.fields:
            return for_all_elements(values, type, depth=depth, argument=argument, original_type=original_type, **other)
        return type.is_simple_buffer(allow_handle=True).if_then_else(
            simple_buffer_case,
            Expr(type.transfer).equals("NW_BUFFER").if_then_else(
                buffer_case,
                default_case
            )
        ).scope()
Example #18
0
 def simple_buffer_case():
     if not hasattr(type, "pointee"):
         return """abort_with_reason("Reached code to handle buffer in non-pointer type.");"""
     copy_code = Expr(arg.output).if_then_else(
         f"""memcpy({param_value}, {src_name}, {size_to_bytes("__buffer_size", type)});""")
     if copy_code:
         return Expr(local_value).not_equals("NULL").if_then_else(
             f"""
             {get_buffer_code()}
             {copy_code}
             """.strip()
         )
     else:
         return ""
Example #19
0
    def convert_result_value(values, cast_type: Type, type_: Type, depth, original_type=None, **other) -> str:
        if isinstance(type_, ConditionalType):
            return Expr(type_.predicate).if_then_else(
                convert_result_value(
                    values, type_.then_type, type_.then_type, depth, original_type=type_.original_type, **other
                ),
                convert_result_value(
                    values, type_.else_type, type_.else_type, depth, original_type=type_.original_type, **other
                ),
            )

        if type_.is_void:
            return """abort_with_reason("Reached code to handle void value.");"""

        (param_value,) = values
        buffer_pred = Expr(type_.transfer).equals("NW_BUFFER") & Expr(param_value).not_equals("NULL")

        def simple_buffer_case():
            return ""

        def buffer_case():
            if not hasattr(type_, "pointee"):
                return """abort_with_reason("Reached code to handle buffer in non-pointer type.");"""
            tmp_name = f"__tmp_{arg.name}_{depth}"
            inner_values = (tmp_name,)
            loop = for_all_elements(inner_values, cast_type, type_, depth=depth, original_type=original_type, **other)
            if loop:
                return buffer_pred.if_then_else(
                    f"""
                     {type_.nonconst.attach_to(tmp_name)};
                     {tmp_name} = {param_value};
                     {loop}
                    """
                )
            return ""

        def default_case():
            return (Expr(type_.transfer).equals("NW_HANDLE")).if_then_else(
                Expr(not type_.deallocates).if_then_else(
                    assign_record_replay_functions(param_value, type_).then(record_call_metadata(param_value, type_)),
                    expunge_calls(param_value),
                )
            )

        if type_.fields:
            return for_all_elements(values, cast_type, type_, depth=depth, original_type=original_type, **other)
        return type_.is_simple_buffer().if_then_else(
            simple_buffer_case, Expr(type_.transfer).equals("NW_BUFFER").if_then_else(buffer_case, default_case)
        )
Example #20
0
def get_transfer_buffer_expr(value, type, *, not_null=False) -> ExprOrStr:
    """
    Generate an expression that gets the transfer buffer of `value` (which has `type`).
    :param value: The value whose transfer buffer to get.
    :param type: The type of value.
    :param not_null: If True, then this function does not generate NULL checks.
    :return: A C expression.
    """
    return (Expr(value).not_equals("NULL") | not_null).if_then_else_expression(
        Expr(type.transfer).equals("NW_BUFFER").if_then_else_expression(
            f"({type.spelling})command_channel_get_buffer(__chan, __cmd, {value})",
            Expr(type.transfer).equals("NW_ZEROCOPY_BUFFER").
            if_then_else_expression(
                f"({type.spelling})ava_zcopy_region_decode_position_independent(__ava_endpoint.zcopy_region, {value})",
                f"({type.spelling}){value}")), f"({type.spelling}){value}")
Example #21
0
        def buffer_case():
            if not hasattr(type_, "pointee"):
                return """abort_with_reason("Reached code to handle buffer in non-pointer type.");"""
            if not arg.output:
                return simple_buffer_case()

            tmp_name = f"__tmp_{arg.name}_{depth}"
            size_name = f"__size_{arg.name}_{depth}"
            inner_values = (tmp_name, local_value)
            return (
                Expr(local_value)
                .not_equals("NULL")
                .if_then_else(
                    f"""{{
                {allocate_tmp_buffer(tmp_name, size_name, type_, alloc_list=alloc_list, original_type=original_type)}
                {for_all_elements(
                    inner_values,
                    cast_type,
                    type_,
                    precomputed_size=size_name,
                    depth=depth,
                    original_type=original_type,
                    **other
                )}
                {attach_data(tmp_name)}
                }}""",
                    f"{param_value} = NULL;",
                )
            )
Example #22
0
def record_call_metadata(handle: str, type_: Optional[Type]) -> Expr:
    log_call_command = """if(__call_log_offset == -1) {
        __call_log_offset =
            command_channel_log_transfer_command((struct command_channel_log*)__log, __chan, (const struct command_base *)__cmd);
    }
    assert(__call_log_offset != -1);"""
    log_ret_command = """if(__ret_log_offset == -1) {
        __ret_log_offset =
            command_channel_log_transfer_command((struct command_channel_log*)__log, __chan, (const struct command_base *)__ret);
    }
    assert(__ret_log_offset != -1);"""

    def dep(dependent, dependency):
        return f"ava_add_dependency(&__ava_endpoint, {dependent}, {dependency});"

    return (
        Expr(type_ is None or type_.object_record).if_then_else(
            f"""
        {log_call_command}{log_ret_command}
        ava_add_recorded_call(&__ava_endpoint, {handle}, ava_new_offset_pair(__call_log_offset, __ret_log_offset));
        """
        )
        # pylint: disable=superfluous-parens
        .then(lines(dep(handle, h) for h in (type_.object_depends_on if type_ else [])))
    )
Example #23
0
def get_buffer_expr(value: str,
                    type: Type,
                    *,
                    not_null=False,
                    size_out=None) -> Expr:
    """
    Generate an expression that finds the local buffer to use for `value`.
    :param value: The value.
    :param type: The type of value.
    :param not_null: If True, then this function does not generate NULL checks.
    :param size_out: If non-None, fill the existing variable with the buffer size in BYTES.
    :return: A C expression.
    """
    if size_out:
        # handle cast of volative size_t* to size_t* explicitly for default
        # buffer size expr
        if size_out == "__buffer_size":
            size_out = "(size_t*)&" + size_out
        else:
            size_out = "&" + size_out
    else:
        size_out = "NULL"
    return (
        type.lifetime.not_equals("AVA_CALL") &
        (Expr(value).not_equals("NULL") | not_null)).if_then_else_expression(
            f"""
        ({type.spelling})ava_shadow_buffer_get_buffer(&__ava_endpoint, __chan, __cmd, {value},
                {type.lifetime}, {type.lifetime_coupled},
                {size_out}, {type.buffer_allocator}, {type.buffer_deallocator})
        """,
            (type.lifetime.equals("AVA_CALL") & type.transfer.one_of(
                {"NW_BUFFER", "NW_ZEROCOPY_BUFFER"})).if_then_else_expression(
                    get_transfer_buffer_expr(value, type, not_null=not_null),
                    f"({type.spelling}){value}"),
        )
Example #24
0
        def buffer_case():
            if not hasattr(type_, "pointee"):
                return """abort_with_reason("Reached code to handle buffer in non-pointer type.");"""
            if not arg.input:
                return simple_buffer_case()

            inner_values = (local_value, src_name)
            core = for_all_elements(
                inner_values,
                local_value_type,
                type_,
                depth=depth,
                precomputed_size="__buffer_size",
                original_type=original_type,
                **other,
            )
            return (
                (type_.lifetime.not_equals("AVA_CALL") | arg.input) & Expr(param_value).not_equals("NULL")
            ).if_then_else(
                f"""
                        {get_buffer_code()}
                        {core}
                        """.strip(),
                maybe_alloc_local_temporary_buffer,
            )
Example #25
0
File: caller.py Project: yuhc/ava
        def buffer_case():
            if not hasattr(type_, "pointee"):
                return """abort_with_reason("Reached code to handle buffer in non-pointer type.");"""
            if not arg.output:
                return simple_buffer_case()

            inner_values = (param_value, src_name)
            loop = for_all_elements(
                inner_values,
                cast_type,
                type_,
                depth=depth,
                precomputed_size="__buffer_size",
                original_type=original_type,
                **other,
            )
            if loop:
                return (
                    Expr(local_value)
                    .not_equals("NULL")
                    .if_then_else(
                        f"""
                    {get_buffer_code()}
                    {loop}
                    """
                    )
                )
            return ""
Example #26
0
 def simple_buffer_case():
     if not hasattr(type_, "pointee"):
         return """abort_with_reason("Reached code to handle buffer in non-pointer type.");"""
     copy_code = (Expr(arg.input) & Expr(local_value).not_equals(src_name)).if_then_else(
         f"""memcpy({local_value}, {src_name}, {size_to_bytes("__buffer_size", type_)});"""
     )
     return (
         (type_.lifetime.not_equals("AVA_CALL") | arg.input) & Expr(param_value).not_equals("NULL")
     ).if_then_else(
         f"""
             {get_buffer_code()}
             {copy_code}
         """.strip(),
         (Expr(arg.input) | type_.transfer.equals("NW_ZEROCOPY_BUFFER")).if_then_else(
             preassignment, maybe_alloc_local_temporary_buffer
         ),
     )
Example #27
0
 def maybe_alloc_local_temporary_buffer():
     # TODO: Deduplicate with allocate_tmp_buffer
     allocator = type.buffer_allocator
     deallocator = type.buffer_deallocator
     return Expr(param_value).not_equals("NULL").if_then_else(f"""{{
     const size_t __size = {compute_buffer_size(type, original_type)};                                   
     {local_value} = ({type.nonconst.spelling}){allocator}({size_to_bytes("__size", type)});    
     {alloc_list.insert(local_value, deallocator)}
     }}""")
Example #28
0
def assign_record_replay_functions(local_value, type: Type) -> Expr:
    extract: Expr = type.object_explicit_state_extract
    replace: Expr = type.object_explicit_state_replace
    return (
        extract.not_equals("NULL") | replace.not_equals("NULL")
    ).if_then_else(
        Expr(
            f"ava_assign_record_replay_functions(&__ava_endpoint, (void*){local_value}, {extract}, {replace});"
        ))
Example #29
0
        def print_value_deep(values, cast_type: Type, type: Type, depth,
                             no_depends, argument, **other):
            (value, ) = values
            if type.is_void:
                return ""
            buffer_pred = Expr(type.transfer).equals("NW_BUFFER") & Expr(
                value).not_equals("NULL")

            def address():
                if not hasattr(type, "pointee"):
                    return """abort_with_reason("Reached code to handle buffer in non-pointer type.");"""
                tmp_name = f"__tmp_{argument.name}_{depth}"
                inner_values = (tmp_name, )
                data_code = buffer_pred.if_then_else(f"""
                    fprintf(file, " = {{");
                    {type.nonconst.attach_to(tmp_name)};
                    {tmp_name} = ({cast_type})({get_transfer_buffer_expr(value, type)});
                    {for_all_elements(inner_values, cast_type, type, precomputed_size=Expr(1), depth=depth, argument=argument, no_depends=no_depends, **other)}
                    fprintf(file, ",...}}");
                    """)
                return f"""
                {printf("ptr 0x%012lx", f"(long int){value}")}
                {data_code}
                """

            def handle():
                return printf("handle %#lx", f"(long int){value}")

            def opaque():
                st = str(type)
                if "*" in st:
                    return printf("%#lx", f"(long int){value}")
                elif "int" in st:
                    return printf("%ld", f"(long int){value}")
                elif "float" in st or "double" in st:
                    return printf("%Lf", f"(long double){value}")
                else:
                    # Fall back on pointer representation
                    return printf("%#lx", f"(long int){value}")

            return Expr(bool(
                type.fields
                or argument.depends_on and no_depends)).if_then_else(
                    "",  # Using only else branch
                    Expr(type.transfer).equals("NW_BUFFER").if_then_else(
                        address,
                        Expr(type.transfer).equals(
                            "NW_ZEROCOPY_BUFFER").if_then_else(
                                address,
                                Expr(type.transfer).equals(
                                    "NW_OPAQUE").if_then_else(
                                        opaque,
                                        Expr(type.transfer).equals(
                                            "NW_HANDLE").if_then_else(handle)),
                            ),
                    ),
                )
Example #30
0
 def add_buffer_size():
     size_expr = size_to_bytes(compute_buffer_size(type, original_type),
                               type)
     return Expr(copy_pred(argument)).if_then_else(
         type.lifetime.equals("AVA_CALL").if_then_else(
             f"{size} += command_channel_buffer_size(__chan, {size_expr});\n",
             f"{size} += ava_shadow_buffer_size(&__ava_endpoint, __chan, {size_expr});\n"
         ),
         type.lifetime.equals("AVA_CALL").if_then_else(
             "",
             f"{size} += ava_shadow_buffer_size_without_data(&__ava_endpoint, __chan, {size_expr});\n"
         ))