import sys
class Target(Enum):
- CSHARP = 1,
+ WINDOWS = 1,
+ LINUX = 2,
+ PTHREAD = 3,
def first_to_lower(string: str) -> str:
first = string[0]
}
}"""
+ self.witness_program_defn = """public class WitnessProgram : CommonBase {
+ /** The witness program bytes themselves */
+ public readonly byte[] program;
+ /** The witness version */
+ public readonly WitnessVersion version;
+
+ internal WitnessProgram(object _dummy, long ptr) : base(ptr) {
+ this.program = InternalUtils.decodeUint8Array(bindings.WitnessProgram_get_program(ptr));
+ this.version = new WitnessVersion(bindings.WitnessProgram_get_version(ptr));
+ }
+ static private long check_args(byte[] program, WitnessVersion version) {
+ if (program.Length < 2 || program.Length > 40) throw new ArgumentException();
+ if (version.getVal() == 0 && program.Length != 20 && program.Length != 32) throw new ArgumentException();
+ return InternalUtils.encodeUint8Array(program);
+ }
+ public WitnessProgram(byte[] program, WitnessVersion version) :
+ this(null, bindings.WitnessProgram_new(version.getVal(), check_args(program, version))) {}
+
+ ~WitnessProgram() {
+ if (ptr != 0) { bindings.WitnessProgram_free(ptr); }
+ }
+}"""
self.c_file_pfx = """
// On OSX jlong (ie long long) is not equivalent to int64_t, so we override here
self.c_file_pfx = self.c_file_pfx + "#include <stdio.h>\n#define DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__)\n"
- if not DEBUG or sys.platform == "darwin":
+ if self.target == Target.WINDOWS:
+ self.c_file_pfx = self.c_file_pfx + """#include <heapapi.h>
+static HANDLE process_heap = NULL;
+static inline void* init_heap() {
+ if (UNLIKELY(process_heap == NULL)) {
+ // Assume pointer writes wont tear, which is true where we need it.
+ process_heap = GetProcessHeap();
+ }
+}
+static inline void* MALLOC(size_t a, const char* _) {
+ init_heap();
+ return HeapAlloc(process_heap, HEAP_ZERO_MEMORY, a);
+}
+#define do_MALLOC(a, b, _c) MALLOC(a, b)
+#define FREE(p) if ((uint64_t)(p) > 4096) { init_heap(); HeapFree(process_heap, 0, p); }
+#define CHECK_ACCESS(p)
+#define CHECK_INNER_FIELD_ACCESS_OR_NULL(v)
+"""
+ elif not DEBUG or self.target != Target.LINUX:
self.c_file_pfx = self.c_file_pfx + """#define do_MALLOC(a, _b, _c) malloc(a)
#define MALLOC(a, _) malloc(a)
#define FREE(p) if ((uint64_t)(p) > 4096) { free(p); }
}
"""
- if sys.platform != "darwin":
+ if self.target == Target.LINUX:
self.c_file_pfx += """
// Running a leak check across all the allocations and frees of the JDK is a mess,
// so instead we implement our own naive leak checker here, relying on the -wrap
_Static_assert(sizeof(void*) <= 8, "Pointers must fit into 64 bits");
+// Int types across Windows/Linux are different, so make sure we're using the right headers.
+_Static_assert(sizeof(void*) == sizeof(uintptr_t), "stdints must be correct");
+_Static_assert(sizeof(void*) == sizeof(intptr_t), "stdints must be correct");
+_Static_assert(sizeof(uint64_t) == 8, "stdints must be correct");
+_Static_assert(sizeof(int64_t) == 8, "stdints must be correct");
+_Static_assert(sizeof(uint32_t) == 4, "stdints must be correct");
+_Static_assert(sizeof(int32_t) == 4, "stdints must be correct");
+_Static_assert(sizeof(uint16_t) == 2, "stdints must be correct");
+_Static_assert(sizeof(int16_t) == 2, "stdints must be correct");
+_Static_assert(sizeof(uint8_t) == 1, "stdints must be correct");
+_Static_assert(sizeof(int8_t) == 1, "stdints must be correct");
+
#define DECL_ARR_TYPE(ty, name) \\
struct name##array { \\
uint64_t arr_len; /* uint32_t would suffice but we want to align uint64_ts as well */ \\
}}
}}
public delegate {jret} {fn_suffix}_callback(int obj_ptr, int fn_id{jargs});
+ static {fn_suffix}_callback {fn_suffix}_callback_inst = c_callback_{fn_suffix};
""")
bindings.write(self.native_meth_decl(f"register_{fn_suffix}_invoker", "int") + f"({fn_suffix}_callback callee);\n")
# Easiest way to get a static run is just define a variable, even if we dont care
- bindings.write(f"\tstatic int _run_{fn_suffix}_registration = register_{fn_suffix}_invoker(c_callback_{fn_suffix});")
+ bindings.write(f"\tstatic int _run_{fn_suffix}_registration = register_{fn_suffix}_invoker({fn_suffix}_callback_inst);")
bindings.write("""
}