Пример #1
0
Файл: caller.py Проект: 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 ""
Пример #2
0
Файл: caller.py Проект: 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;",
            )
Пример #3
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,
            )
Пример #4
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()
Пример #5
0
 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))
Пример #6
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()
Пример #7
0
 def buffer_case():
     if not hasattr(type, "pointee"):
         return """abort_with_reason("Reached code to handle buffer in non-pointer type.");"""
     loop = for_all_elements(values,
                             type,
                             depth=depth,
                             argument=argument,
                             original_type=original_type,
                             **other)
     outer_buffer = str(add_buffer_size())
     return pred.if_then_else(loop + outer_buffer)
Пример #8
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()
Пример #9
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)
        )
Пример #10
0
 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 ""
Пример #11
0
    def compute_size(values,
                     type: Type,
                     depth,
                     argument: Argument,
                     original_type=None,
                     **other):
        if isinstance(type, ConditionalType):
            return Expr(type.predicate).if_then_else(
                compute_size(values,
                             type.then_type,
                             depth,
                             argument,
                             original_type=type.original_type,
                             **other),
                compute_size(values,
                             type.else_type,
                             depth,
                             argument,
                             original_type=type.original_type,
                             **other))

        value, = values
        pred = Expr(type.transfer).equals("NW_BUFFER") & Expr(
            value).not_equals("NULL") & (Expr(type.buffer) > 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"
                ))

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

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

        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, lambda: Expr(type.transfer).equals("NW_BUFFER")
            .if_then_else(buffer_case))
Пример #12
0
    def convert_input_value(values,
                            type: Type,
                            depth,
                            original_type=None,
                            **other):
        local_value, param_value = values
        preassignment = f"{local_value} = {get_transfer_buffer_expr(param_value, type)};"

        if isinstance(type, ConditionalType):
            return Expr(preassignment).then(
                Expr(type.predicate).if_then_else(
                    convert_input_value(values,
                                        type.then_type,
                                        depth,
                                        original_type=type.original_type,
                                        **other),
                    convert_input_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.");"""

        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)}
            }}""")

        src_name = f"__src_{arg.name}_{depth}"

        def get_buffer_code():
            return f"""
                {type.nonconst.attach_to(src_name)};
                {src_name} = {local_value};
                {get_buffer(local_value, param_value, type, original_type=original_type, not_null=True)}
                {(type.lifetime.equals("AVA_CALL") & (~type.is_simple_buffer() | type.buffer_allocator.not_equals("malloc"))).if_then_else(
                        maybe_alloc_local_temporary_buffer)}
                """

        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))

        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,
                                    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)

        def default_case():
            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.");"""
                        )))

            return Expr(type.deallocates).if_then_else(
                deref_code("nw_handle_pool_deref_and_remove"),
                deref_code("nw_handle_pool_deref"))

        if type.fields:
            return for_all_elements(values, type, depth=depth, **other)
        rest = type.is_simple_buffer().if_then_else(
            simple_buffer_case,
            Expr(type.transfer).equals("NW_BUFFER").if_then_else(
                buffer_case, default_case))
        if rest:
            return Expr(preassignment).then(rest).scope()
        else:
            return ""
Пример #13
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.");"""

        param_value, local_value = values

        def attach_data(data):
            return attach_buffer(param_value,
                                 local_value,
                                 data,
                                 type,
                                 arg.output,
                                 cmd=dest,
                                 original_type=original_type,
                                 expect_reply=False)

        def simple_buffer_case():
            if not hasattr(type, "pointee"):
                return """abort_with_reason("Reached code to handle buffer in non-pointer type.");"""
            return (Expr(local_value).not_equals("NULL") &
                    (Expr(type.buffer) > 0)).if_then_else(
                        attach_data(local_value), f"{param_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.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, type, precomputed_size=size_name, depth=depth, original_type=original_type, **other)}
                {attach_data(tmp_name)}
                }}""", f"{param_value} = NULL;")

        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};"))

        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()
Пример #14
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))

        param_value, local_value = values

        src_name = f"__src_{arg.name}_{depth}"

        def get_buffer_code():
            nonlocal reported_missing_lifetime
            if not reported_missing_lifetime and \
                    ((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} = {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, 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);")
                ))

        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 ""

        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, 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}
                    """
                )
            else:
                return ""

        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};"))

        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
                )
            )
        ).scope()