From d236cdeb79c96691aff80ccb7d546220ed9b94d8 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 29 Jan 2021 23:21:27 -0500 Subject: [PATCH] Add a reference low bit for non-opaque types to tag dont-free refs --- gen_type_mapping.py | 19 +++++++++------ genbindings.py | 48 ++++++++++++++++++++++-------------- java_strings.py | 57 ++++++++++++++++++++++--------------------- typescript_strings.py | 54 ++++++++++++++++++++-------------------- 4 files changed, 97 insertions(+), 81 deletions(-) diff --git a/gen_type_mapping.py b/gen_type_mapping.py index f57592f4..d323de1c 100644 --- a/gen_type_mapping.py +++ b/gen_type_mapping.py @@ -258,8 +258,14 @@ class TypeMappingGenerator: arg_conv_cleanup = None, ret_conv = (ty_info.c_ty + " " + ty_info.var_name + "_conv = " + ret_pfx, ret_sfx + ";"), ret_conv_name = ty_info.var_name + "_conv", to_hu_conv = None, to_hu_conv_name = None, from_hu_conv = None) - base_conv = ty_info.rust_obj + " " + ty_info.var_name + "_conv = *(" + ty_info.rust_obj + "*)" + ty_info.var_name + ";" + base_conv = ty_info.rust_obj + " " + ty_info.var_name + "_conv = *(" + ty_info.rust_obj + "*)(((uint64_t)" + ty_info.var_name + ") & ~1);" if ty_info.rust_obj in self.trait_structs: + ret_conv = (ty_info.rust_obj + "* ret = MALLOC(sizeof(" + ty_info.rust_obj + "), \"" + ty_info.rust_obj + "\");\n*ret = ", ";") + if holds_ref: + if (ty_info.rust_obj.replace("LDK", "") + "_clone") in self.clone_fns: + ret_conv = (ret_conv[0] + ty_info.rust_obj.replace("LDK", "") + "_clone(&", ");") + else: + ret_conv = (ret_conv[0], "; // XXX: We likely need to clone here, but no _clone fn is available!") if not is_free: needs_full_clone = not is_free and (not ty_info.is_ptr and not holds_ref or ty_info.requires_clone == True) and ty_info.requires_clone != False if needs_full_clone and (ty_info.rust_obj.replace("LDK", "") + "_clone") in self.clone_fns: @@ -272,8 +278,7 @@ class TypeMappingGenerator: base_conv = base_conv + "\n" + "FREE((void*)" + ty_info.var_name + ");" return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name, arg_conv = base_conv, arg_conv_name = ty_info.var_name + "_conv", arg_conv_cleanup = None, - ret_conv = (ty_info.rust_obj + "* ret = MALLOC(sizeof(" + ty_info.rust_obj + "), \"" + ty_info.rust_obj + "\");\n*ret = ", ";"), - ret_conv_name = "(long)ret", + ret_conv = ret_conv, ret_conv_name = "(long)ret", to_hu_conv = ty_info.java_hu_ty + " ret_hu_conv = new " + ty_info.java_hu_ty + "(null, " + ty_info.var_name + ");\nret_hu_conv.ptrs_to.add(this);", to_hu_conv_name = "ret_hu_conv", from_hu_conv = (ty_info.var_name + " == null ? 0 : " + ty_info.var_name + ".ptr", "this.ptrs_to.add(" + ty_info.var_name + ")")) @@ -290,7 +295,7 @@ class TypeMappingGenerator: # underlying unlike Vecs, and it gives Java more freedom. base_conv = base_conv + "\nFREE((void*)" + ty_info.var_name + ");" if ty_info.rust_obj in self.complex_enums: - ret_conv = ("long " + ty_info.var_name + "_ref = (long)&", ";") + ret_conv = ("long " + ty_info.var_name + "_ref = ((long)&", ") | 1;") if not holds_ref: ret_conv = (ty_info.rust_obj + " *" + ty_info.var_name + "_copy = MALLOC(sizeof(" + ty_info.rust_obj + "), \"" + ty_info.rust_obj + "\");\n", "") if ty_info.requires_clone == True: # Set in object array mapping @@ -367,7 +372,7 @@ class TypeMappingGenerator: to_hu_conv = to_hu_conv_pfx + to_hu_conv_sfx + ");", to_hu_conv_name = ty_info.var_name + "_conv", from_hu_conv = (from_hu_conv + ")", "")) return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name, arg_conv = base_conv, arg_conv_name = ty_info.var_name + "_conv", arg_conv_cleanup = None, - ret_conv = ("long " + ty_info.var_name + "_ref = (long)&", ";"), ret_conv_name = ty_info.var_name + "_ref", + ret_conv = ("long " + ty_info.var_name + "_ref = (long)(&", ") | 1;"), ret_conv_name = ty_info.var_name + "_ref", to_hu_conv = to_hu_conv_pfx + to_hu_conv_sfx + ");", to_hu_conv_name = ty_info.var_name + "_conv", from_hu_conv = (from_hu_conv + ")", "")) # The manually-defined types - TxOut and Transaction @@ -375,7 +380,7 @@ class TypeMappingGenerator: if not ty_info.is_ptr and not holds_ref: ret_conv = ("LDKTxOut* " + ty_info.var_name + "_ref = MALLOC(sizeof(LDKTxOut), \"LDKTxOut\");\n*" + ty_info.var_name + "_ref = ", ";") else: - ret_conv = ("long " + ty_info.var_name + "_ref = (long)&", ";") + ret_conv = ("long " + ty_info.var_name + "_ref = ((long)&", ") | 1;") return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name, arg_conv = base_conv, arg_conv_name = ty_info.var_name + "_conv", arg_conv_cleanup = None, ret_conv = ret_conv, ret_conv_name = "(long)" + ty_info.var_name + "_ref", @@ -411,7 +416,7 @@ class TypeMappingGenerator: to_hu_conv_name = "ret_hu_conv", from_hu_conv = (ty_info.var_name + " == null ? 0 : " + ty_info.var_name + ".ptr", "this.ptrs_to.add(" + ty_info.var_name + ")")) return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name, - arg_conv = ty_info.rust_obj + "* " + ty_info.var_name + "_conv = (" + ty_info.rust_obj + "*)" + ty_info.var_name + ";", + arg_conv = ty_info.rust_obj + "* " + ty_info.var_name + "_conv = (" + ty_info.rust_obj + "*)(" + ty_info.var_name + " & ~1);", arg_conv_name = ty_info.var_name + "_conv", arg_conv_cleanup = None, ret_conv = ("long ret_" + ty_info.var_name + " = (long)", ";"), ret_conv_name = "ret_" + ty_info.var_name, to_hu_conv = "TODO 3", to_hu_conv_name = None, from_hu_conv = None) # its a pointer, no conv needed diff --git a/genbindings.py b/genbindings.py index 96fafb70..acc757b1 100755 --- a/genbindings.py +++ b/genbindings.py @@ -360,12 +360,12 @@ write_c("static inline struct LDKThirtyTwoBytes ThirtyTwoBytes_clone(const struc java_c_types_none_allowed = False # C structs created by cbindgen are declared in dependency order -with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: +with open(f"{sys.argv[3]}/structs/UtilMethods{consts.file_ext}", "a") as util: + util.write(consts.util_fn_pfx) +with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: # Map a top-level function def map_fn(line, re_match, ret_arr_len, c_call_string): - - # PARSING START method_return_type = re_match.group(1) method_name = re_match.group(2) method_comma_separated_arguments = re_match.group(3) @@ -400,24 +400,36 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: default_constructor_args[argument_conversion_info.arg_name].append(explode_arg_conv) argument_types.append(argument_conversion_info) - has_out_java_struct = ("LDK" + struct_meth in opaque_structs or "LDK" + struct_meth in trait_structs) and not is_free - # PARSING END - out_java.write("\t// " + line) - - (out_java_delta, out_c_delta, out_java_struct_delta) = consts.map_function(argument_types, c_call_string, is_free, method_name, return_type_info, struct_meth, default_constructor_args, takes_self, args_known, has_out_java_struct, type_mapping_generator) - + (out_java_delta, out_c_delta, out_java_struct_delta) = consts.map_function(argument_types, c_call_string, method_name, return_type_info, struct_meth, default_constructor_args, takes_self, args_known, type_mapping_generator) out_java.write(out_java_delta) - write_c(out_c_delta) - if has_out_java_struct: + if is_free: + assert len(argument_types) == 1 + assert return_type_info.c_ty == "void" + write_c(consts.c_fn_ty_pfx + "void " + consts.c_fn_name_define_pfx(method_name, True) + argument_types[0].c_ty + " " + argument_types[0].ty_info.var_name + ") {\n") + if argument_types[0].ty_info.passed_as_ptr and not argument_types[0].ty_info.rust_obj in opaque_structs: + write_c("\tif ((" + argument_types[0].ty_info.var_name + " & 1) != 0) return;\n") + + for info in argument_types: + if info.arg_conv is not None: + write_c("\t" + info.arg_conv.replace('\n', "\n\t") + "\n") + assert c_call_string is None + write_c("\t" + method_name + "(") + if argument_types[0].arg_conv_name is not None: + write_c(argument_types[0].arg_conv_name) + write_c(");") + for info in argument_types: + if info.arg_conv_cleanup is not None: + write_c("\n\t" + info.arg_conv_cleanup.replace("\n", "\n\t")) + write_c("\n}\n\n") + else: + write_c(out_c_delta) + + if ("LDK" + struct_meth in opaque_structs or "LDK" + struct_meth in trait_structs) and not is_free: out_java_struct = open(f"{sys.argv[3]}/structs/{struct_meth}{consts.file_ext}", "a") out_java_struct.write(out_java_struct_delta) - - - - def map_unitary_enum(struct_name, field_lines): with open(f"{sys.argv[3]}/enums/{struct_name}{consts.file_ext}", "w") as out_java_enum: unitary_enums.add(struct_name) @@ -550,7 +562,7 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: out_java.write("\tpublic static native " + res_map.java_ty + " " + struct_name + "_get_ok(long arg);\n") write_c(consts.c_fn_ty_pfx + res_map.c_ty + " " + consts.c_fn_name_define_pfx(struct_name + "_get_ok", True) + consts.ptr_c_ty + " arg) {\n") - write_c("\t" + struct_name + " *val = (" + struct_name + "*)arg;\n") + write_c("\t" + struct_name + " *val = (" + struct_name + "*)(arg & ~1);\n") write_c("\tCHECK(val->result_ok);\n\t") out_java_struct.write("\tpublic static final class " + human_ty + "_OK extends " + human_ty + " {\n") if res_map.ret_conv is not None: @@ -587,7 +599,7 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: out_java.write("\tpublic static native " + err_map.java_ty + " " + struct_name + "_get_err(long arg);\n") write_c(consts.c_fn_ty_pfx + err_map.c_ty + " " + consts.c_fn_name_define_pfx(struct_name + "_get_err", True) + consts.ptr_c_ty + " arg) {\n") - write_c("\t" + struct_name + " *val = (" + struct_name + "*)arg;\n") + write_c("\t" + struct_name + " *val = (" + struct_name + "*)(arg & ~1);\n") write_c("\tCHECK(!val->result_ok);\n\t") out_java_struct.write("\tpublic static final class " + human_ty + "_Err extends " + human_ty + " {\n") if err_map.ret_conv is not None: @@ -659,7 +671,7 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: e = chr(ord('a') + idx) out_java.write("\tpublic static native " + ty_info.java_ty + " " + struct_name + "_get_" + e + "(long ptr);\n") write_c(consts.c_fn_ty_pfx + ty_info.c_ty + " " + consts.c_fn_name_define_pfx(struct_name + "_get_" + e, True) + consts.ptr_c_ty + " ptr) {\n") - write_c("\t" + struct_name + " *tuple = (" + struct_name + "*)ptr;\n") + write_c("\t" + struct_name + " *tuple = (" + struct_name + "*)(ptr & ~1);\n") conv_info = type_mapping_generator.map_type_with_info(ty_info, False, None, False, True) if conv_info.ret_conv is not None: write_c("\t" + conv_info.ret_conv[0].replace("\n", "\n\t") + "tuple->" + e + conv_info.ret_conv[1].replace("\n", "\n\t") + "\n") diff --git a/java_strings.py b/java_strings.py index c83ee826..e1ea1e86 100644 --- a/java_strings.py +++ b/java_strings.py @@ -180,11 +180,14 @@ void __wrap_reallocarray(void* ptr, size_t new_sz) { } void __attribute__((destructor)) check_leaks() { + size_t alloc_count = 0; for (allocation* a = allocation_ll; a != NULL; a = a->next) { fprintf(stderr, "%s %p remains:\\n", a->struct_name, a->ptr); backtrace_symbols_fd(a->bt, a->bt_len, STDERR_FILENO); fprintf(stderr, "\\n\\n"); + alloc_count++; } + fprintf(stderr, "%lu allocations remained.\\n", alloc_count); DO_ASSERT(allocation_ll == NULL); } """ @@ -833,7 +836,7 @@ import java.util.Arrays; return out_opaque_struct_human - def map_function(self, argument_types, c_call_string, is_free, method_name, return_type_info, struct_meth, default_constructor_args, takes_self, args_known, has_out_java_struct: bool, type_mapping_generator): + def map_function(self, argument_types, c_call_string, method_name, return_type_info, struct_meth, default_constructor_args, takes_self, args_known, type_mapping_generator): out_java = "" out_c = "" out_java_struct = None @@ -856,33 +859,31 @@ import java.util.Arrays; out_c += (arg_conv_info.c_ty + " " + arg_conv_info.arg_name) out_java += (arg_conv_info.java_ty + " " + arg_conv_info.arg_name) - if has_out_java_struct: - out_java_struct = "" - if not args_known: - out_java_struct += ("\t// Skipped " + method_name + "\n") - has_out_java_struct = False + out_java_struct = "" + if not args_known: + out_java_struct += ("\t// Skipped " + method_name + "\n") + else: + meth_n = method_name[len(struct_meth) + 1:] + if not takes_self: + out_java_struct += ( + "\tpublic static " + return_type_info.java_hu_ty + " constructor_" + meth_n + "(") else: - meth_n = method_name[len(struct_meth) + 1:] - if not takes_self: - out_java_struct += ( - "\tpublic static " + return_type_info.java_hu_ty + " constructor_" + meth_n + "(") - else: - out_java_struct += ("\tpublic " + return_type_info.java_hu_ty + " " + meth_n + "(") - for idx, arg in enumerate(argument_types): - if idx != 0: - if not takes_self or idx > 1: - out_java_struct += (", ") - elif takes_self: - continue - if arg.java_ty != "void": - if arg.arg_name in default_constructor_args: - for explode_idx, explode_arg in enumerate(default_constructor_args[arg.arg_name]): - if explode_idx != 0: - out_java_struct += (", ") - out_java_struct += ( - explode_arg.java_hu_ty + " " + arg.arg_name + "_" + explode_arg.arg_name) - else: - out_java_struct += (arg.java_hu_ty + " " + arg.arg_name) + out_java_struct += ("\tpublic " + return_type_info.java_hu_ty + " " + meth_n + "(") + for idx, arg in enumerate(argument_types): + if idx != 0: + if not takes_self or idx > 1: + out_java_struct += (", ") + elif takes_self: + continue + if arg.java_ty != "void": + if arg.arg_name in default_constructor_args: + for explode_idx, explode_arg in enumerate(default_constructor_args[arg.arg_name]): + if explode_idx != 0: + out_java_struct += (", ") + out_java_struct += ( + explode_arg.java_hu_ty + " " + arg.arg_name + "_" + explode_arg.arg_name) + else: + out_java_struct += (arg.java_hu_ty + " " + arg.arg_name) out_java += (");\n") out_c += (") {\n") if out_java_struct is not None: @@ -921,7 +922,7 @@ import java.util.Arrays; out_c += ("\n\treturn ret_val;") out_c += ("\n}\n\n") - if has_out_java_struct: + if args_known: out_java_struct += ("\t\t") if return_type_info.java_ty != "void": out_java_struct += (return_type_info.java_ty + " ret = ") diff --git a/typescript_strings.py b/typescript_strings.py index 3ac30414..cb1f3828 100644 --- a/typescript_strings.py +++ b/typescript_strings.py @@ -894,7 +894,7 @@ const decodeString = (stringPointer, free = true) => { """ return out_opaque_struct_human - def map_function(self, argument_types, c_call_string, is_free, method_name, return_type_info, struct_meth, default_constructor_args, takes_self, args_known, has_out_java_struct: bool, type_mapping_generator): + def map_function(self, argument_types, c_call_string, method_name, return_type_info, struct_meth, default_constructor_args, takes_self, args_known, type_mapping_generator): out_java = "" out_c = "" out_java_struct = None @@ -943,33 +943,31 @@ const decodeString = (stringPointer, free = true) => { }} """ - if has_out_java_struct: - out_java_struct = "" - if not args_known: - out_java_struct += ("\t// Skipped " + method_name + "\n") - has_out_java_struct = False + out_java_struct = "" + if not args_known: + out_java_struct += ("\t// Skipped " + method_name + "\n") + else: + meth_n = method_name[len(struct_meth) + 1:] + if not takes_self: + out_java_struct += ( + "\tpublic static " + return_type_info.java_hu_ty + " constructor_" + meth_n + "(") else: - meth_n = method_name[len(struct_meth) + 1:] - if not takes_self: - out_java_struct += ( - "\tpublic static " + return_type_info.java_hu_ty + " constructor_" + meth_n + "(") - else: - out_java_struct += ("\tpublic " + return_type_info.java_hu_ty + " " + meth_n + "(") - for idx, arg in enumerate(argument_types): - if idx != 0: - if not takes_self or idx > 1: - out_java_struct += (", ") - elif takes_self: - continue - if arg.java_ty != "void": - if arg.arg_name in default_constructor_args: - for explode_idx, explode_arg in enumerate(default_constructor_args[arg.arg_name]): - if explode_idx != 0: - out_java_struct += (", ") - out_java_struct += ( - explode_arg.java_hu_ty + " " + arg.arg_name + "_" + explode_arg.arg_name) - else: - out_java_struct += (arg.java_hu_ty + " " + arg.arg_name) + out_java_struct += ("\tpublic " + return_type_info.java_hu_ty + " " + meth_n + "(") + for idx, arg in enumerate(argument_types): + if idx != 0: + if not takes_self or idx > 1: + out_java_struct += (", ") + elif takes_self: + continue + if arg.java_ty != "void": + if arg.arg_name in default_constructor_args: + for explode_idx, explode_arg in enumerate(default_constructor_args[arg.arg_name]): + if explode_idx != 0: + out_java_struct += (", ") + out_java_struct += ( + explode_arg.java_hu_ty + " " + arg.arg_name + "_" + explode_arg.arg_name) + else: + out_java_struct += (arg.java_hu_ty + " " + arg.arg_name) out_c += (") {\n") if out_java_struct is not None: @@ -1008,7 +1006,7 @@ const decodeString = (stringPointer, free = true) => { out_c += ("\n\treturn ret_val;") out_c += ("\n}\n\n") - if has_out_java_struct: + if args_known: out_java_struct += ("\t\t") if return_type_info.java_ty != "void": out_java_struct += (return_type_info.java_ty + " ret = ") -- 2.30.2