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 ""
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;", )
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, )
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()
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 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()
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)
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()
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) )
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 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))
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 ""
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()
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()