Add a reference low bit for non-opaque types to tag dont-free refs
authorMatt Corallo <git@bluematt.me>
Sat, 30 Jan 2021 04:21:27 +0000 (23:21 -0500)
committerMatt Corallo <git@bluematt.me>
Mon, 1 Feb 2021 01:08:52 +0000 (20:08 -0500)
gen_type_mapping.py
genbindings.py
java_strings.py
typescript_strings.py

index f57592f40fadf1926105996ae7d15c1e087e68ca..d323de1c3c1d03d6512854f39de3af00deb3a468 100644 (file)
@@ -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
index 96fafb70b39e32f66a4ead0dc2bcc7bbfa9ad8ef..acc757b19b89cd71792805f3c6b611695fd5db33 100755 (executable)
@@ -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")
index c83ee8269257f6a5c66e9f3bbe15cdb26cc3f98b..e1ea1e868e0b60655949ddb4b073a524aa1deed4 100644 (file)
@@ -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 = ")
index 3ac304149a6bee481b10c6503cf92c00a2dcff81..cb1f3828fc06dd4211043435082216d1992d663c 100644 (file)
@@ -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 = ")