From a0ca8930bc59baa61e08f353e57aa91c1737dcd8 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Thu, 28 Apr 2022 06:55:37 -0700 Subject: [PATCH] Add JIT FFI --- src/javascript/jsc/api/FFI.h | 107 +++ src/javascript/jsc/api/bun.zig | 6 + src/javascript/jsc/api/ffi.zig | 797 ++++++++++++++++++ .../jsc/api/libtcc1.a.macos-aarch64 | Bin 0 -> 29988 bytes src/javascript/jsc/base.zig | 2 + src/javascript/jsc/bindings/bindings.zig | 12 + 6 files changed, 924 insertions(+) create mode 100644 src/javascript/jsc/api/FFI.h create mode 100644 src/javascript/jsc/api/ffi.zig create mode 100644 src/javascript/jsc/api/libtcc1.a.macos-aarch64 diff --git a/src/javascript/jsc/api/FFI.h b/src/javascript/jsc/api/FFI.h new file mode 100644 index 0000000000..ffed86138a --- /dev/null +++ b/src/javascript/jsc/api/FFI.h @@ -0,0 +1,107 @@ +// This is an auto-generated file +// +// clang-format off +// This file is only compatible with 64 bit CPUs +// It must be kept in sync with JSCJSValue.h +// https://github.com/Jarred-Sumner/WebKit/blob/72c2052b781cbfd4af867ae79ac9de460e392fba/Source/JavaScriptCore/runtime/JSCJSValue.h#L455-L458 + + +#define IS_BIG_ENDIAN 0 +#define USE_JSVALUE64 1 +#define USE_JSVALUE32_64 0 + +/* 7.18.1.1 Exact-width integer types */ +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned uint32_t; +typedef long long int64_t; +typedef unsigned long long uint64_t; +typedef int64_t intptr_t; +typedef uint64_t uintptr_t; +typedef uintptr_t size_t; + +#define true 1 +#define false 0 +#define bool _bool + +// This value is 2^49, used to encode doubles such that the encoded value will +// begin with a 15-bit pattern within the range 0x0002..0xFFFC. +#define DoubleEncodeOffsetBit (size_t)(49) +#define DoubleEncodeOffset (int64_t)(1ll << DoubleEncodeOffsetBit) +#define OtherTag 0x2 +#define BoolTag 0x4 +#define UndefinedTag 0x8 +#define TagValueFalse (OtherTag | BoolTag | false) +#define TagValueTrue (OtherTag | BoolTag | true) +#define TagValueUndefined (OtherTag | UndefinedTag) +#define TagValueNull (OtherTag) + +// If all bits in the mask are set, this indicates an integer number, +// if any but not all are set this value is a double precision number. +#define NumberTag 0xfffe000000000000ll + +typedef void* JSCell; + +typedef union EncodedJSValue { + int64_t asInt64; +#if USE_JSVALUE32_64 + double asDouble; +#elif USE_JSVALUE64 + JSCell *ptr; +#endif + +#if IS_BIG_ENDIAN + struct { + int32_t tag; + int32_t payload; + } asBits; +#else + struct { + int32_t payload; + int32_t tag; + } asBits; +#endif + + void* asPtr; +} EncodedJSValue; + +EncodedJSValue ValueUndefined = { TagValueUndefined }; +EncodedJSValue ValueTrue = { TagValueTrue }; + + +static EncodedJSValue INT32_TO_JSVALUE(int32_t val); +static EncodedJSValue INT32_TO_JSVALUE(int32_t val) { + EncodedJSValue res; + res.asInt64 = NumberTag | (uint32_t)val; + return res; +} + +#define JSVALUE_IS_TRUE(i) (!!(i.asInt64 == ValueTrue)) +#define JSVALUE_TO_INT32(i) (int32_t)i.asInt64 +#define JSVALUE_TO_DOUBLE(i) ((double)(i.asInt64 - DoubleEncodeOffset)) +#define JSVALUE_TO_FLOAT(i) ((float)(i.asInt64 - DoubleEncodeOffset)) + +#define BOOLEAN_TO_JSVALUE(i) (i ? ValueTrue : ValueFalse) + +#define DOUBLE_TO_JSVALUE(i) ((double)(i.asInt64 - DoubleEncodeOffset)) +#define FLOAT_TO_JSVALUE(i) ((float)(i.asInt64 - DoubleEncodeOffset)) + + + + +typedef void* JSContext; +typedef EncodedJSValue* JSException; + + +// typedef void* (^ArrayBufferLikeGetPtrFunction)(JSContext, EncodedJSValue); +// static ArrayBufferLikeGetPtrFunction JSArrayBufferGetPtr = (ArrayBufferLikeGetPtrFunction)MEMORY_ADDRESS_FOR_GET_ARRAY_BUFFER_FUNCTION; +// (*JSObjectCallAsFunctionCallback) (JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); + +// This is an example of a function which does the bare minimum +void* Bun__CallbackFunctionPlaceholder(JSContext ctx, EncodedJSValue function, EncodedJSValue thisObject, size_t argumentCount, const EncodedJSValue arguments[], JSException exception); +void* Bun__CallbackFunctionPlaceholder(JSContext ctx, EncodedJSValue function, EncodedJSValue thisObject, size_t argumentCount, const EncodedJSValue arguments[], JSException exception) { + return (void*)123; +} diff --git a/src/javascript/jsc/api/bun.zig b/src/javascript/jsc/api/bun.zig index de85d6c8f8..ff6e63724a 100644 --- a/src/javascript/jsc/api/bun.zig +++ b/src/javascript/jsc/api/bun.zig @@ -1121,6 +1121,12 @@ pub const Class = NewClass( .sha = .{ .rfn = JSC.wrapWithHasContainer(Crypto.SHA512_256, "hash", false, false), }, + .dlprint = .{ + .rfn = JSC.wrapWithHasContainer(JSC.FFI, "print", false, false), + }, + .dlopen = .{ + .rfn = JSC.wrapWithHasContainer(JSC.FFI, "open", false, false), + }, }, .{ .main = .{ diff --git a/src/javascript/jsc/api/ffi.zig b/src/javascript/jsc/api/ffi.zig new file mode 100644 index 0000000000..a6191beb0f --- /dev/null +++ b/src/javascript/jsc/api/ffi.zig @@ -0,0 +1,797 @@ +const Bun = @This(); +const default_allocator = @import("../../../global.zig").default_allocator; +const bun = @import("../../../global.zig"); +const Environment = bun.Environment; +const NetworkThread = @import("http").NetworkThread; +const Global = bun.Global; +const strings = bun.strings; +const string = bun.string; +const Output = @import("../../../global.zig").Output; +const MutableString = @import("../../../global.zig").MutableString; +const std = @import("std"); +const Allocator = std.mem.Allocator; +const IdentityContext = @import("../../../identity_context.zig").IdentityContext; +const Fs = @import("../../../fs.zig"); +const Resolver = @import("../../../resolver/resolver.zig"); +const ast = @import("../../../import_record.zig"); +const NodeModuleBundle = @import("../../../node_module_bundle.zig").NodeModuleBundle; +const MacroEntryPoint = @import("../../../bundler.zig").MacroEntryPoint; +const logger = @import("../../../logger.zig"); +const Api = @import("../../../api/schema.zig").Api; +const options = @import("../../../options.zig"); +const Bundler = @import("../../../bundler.zig").Bundler; +const ServerEntryPoint = @import("../../../bundler.zig").ServerEntryPoint; +const js_printer = @import("../../../js_printer.zig"); +const js_parser = @import("../../../js_parser.zig"); +const js_ast = @import("../../../js_ast.zig"); +const hash_map = @import("../../../hash_map.zig"); +const http = @import("../../../http.zig"); +const NodeFallbackModules = @import("../../../node_fallbacks.zig"); +const ImportKind = ast.ImportKind; +const Analytics = @import("../../../analytics/analytics_thread.zig"); +const ZigString = @import("../../../jsc.zig").ZigString; +const Runtime = @import("../../../runtime.zig"); +const Router = @import("./router.zig"); +const ImportRecord = ast.ImportRecord; +const DotEnv = @import("../../../env_loader.zig"); +const ParseResult = @import("../../../bundler.zig").ParseResult; +const PackageJSON = @import("../../../resolver/package_json.zig").PackageJSON; +const MacroRemap = @import("../../../resolver/package_json.zig").MacroMap; +const WebCore = @import("../../../jsc.zig").WebCore; +const Request = WebCore.Request; +const Response = WebCore.Response; +const Headers = WebCore.Headers; +const Fetch = WebCore.Fetch; +const FetchEvent = WebCore.FetchEvent; +const js = @import("../../../jsc.zig").C; +const JSC = @import("../../../jsc.zig"); +const JSError = @import("../base.zig").JSError; +const d = @import("../base.zig").d; +const MarkedArrayBuffer = @import("../base.zig").MarkedArrayBuffer; +const getAllocator = @import("../base.zig").getAllocator; +const JSValue = @import("../../../jsc.zig").JSValue; +const NewClass = @import("../base.zig").NewClass; +const Microtask = @import("../../../jsc.zig").Microtask; +const JSGlobalObject = @import("../../../jsc.zig").JSGlobalObject; +const ExceptionValueRef = @import("../../../jsc.zig").ExceptionValueRef; +const JSPrivateDataPtr = @import("../../../jsc.zig").JSPrivateDataPtr; +const ZigConsoleClient = @import("../../../jsc.zig").ZigConsoleClient; +const Node = @import("../../../jsc.zig").Node; +const ZigException = @import("../../../jsc.zig").ZigException; +const ZigStackTrace = @import("../../../jsc.zig").ZigStackTrace; +const ErrorableResolvedSource = @import("../../../jsc.zig").ErrorableResolvedSource; +const ResolvedSource = @import("../../../jsc.zig").ResolvedSource; +const JSPromise = @import("../../../jsc.zig").JSPromise; +const JSInternalPromise = @import("../../../jsc.zig").JSInternalPromise; +const JSModuleLoader = @import("../../../jsc.zig").JSModuleLoader; +const JSPromiseRejectionOperation = @import("../../../jsc.zig").JSPromiseRejectionOperation; +const Exception = @import("../../../jsc.zig").Exception; +const ErrorableZigString = @import("../../../jsc.zig").ErrorableZigString; +const ZigGlobalObject = @import("../../../jsc.zig").ZigGlobalObject; +const VM = @import("../../../jsc.zig").VM; +const JSFunction = @import("../../../jsc.zig").JSFunction; +const Config = @import("../config.zig"); +const URL = @import("../../../url.zig").URL; +const Transpiler = @import("./transpiler.zig"); +const VirtualMachine = @import("../javascript.zig").VirtualMachine; +const IOTask = JSC.IOTask; +const ComptimeStringMap = @import("../../../comptime_string_map.zig").ComptimeStringMap; + +const TCC = @import("../../../../tcc.zig"); + +pub const FFI = struct { + dylib: std.DynLib, + functions: std.StringArrayHashMapUnmanaged(Function) = .{}, + closed: bool = false, + + pub const Class = JSC.NewClass( + FFI, + .{ .name = "class" }, + .{ .call = JSC.wrapWithHasContainer(FFI, "close", false, true) }, + .{}, + ); + + pub fn close(this: *FFI) JSValue { + if (this.closed) { + return JSC.JSValue.jsUndefined(); + } + this.closed = true; + this.dylib.close(); + + for (this.functions.values()) |*val| { + VirtualMachine.vm.allocator.free(bun.constStrToU8(std.mem.span(val.base_name))); + + val.arg_types.deinit(VirtualMachine.vm.allocator); + } + this.functions.deinit(VirtualMachine.vm.allocator); + + return JSC.JSValue.jsUndefined(); + } + + pub fn print(global: *JSGlobalObject, object: JSC.JSValue) JSValue { + const allocator = VirtualMachine.vm.allocator; + + if (object.isEmptyOrUndefinedOrNull() or !object.isObject()) { + return JSC.toInvalidArguments("Expected an options object with symbol names", .{}, global.ref()); + } + + var symbols = std.StringArrayHashMapUnmanaged(Function){}; + if (generateSymbols(global, &symbols, object) catch JSC.JSValue.zero) |val| { + // an error while validating symbols + for (symbols.keys()) |key| { + allocator.free(bun.constStrToU8(key)); + } + symbols.clearAndFree(allocator); + return val; + } + + var zig_strings = allocator.alloc(ZigString, symbols.count()) catch unreachable; + for (symbols.values()) |*function, i| { + var arraylist = std.ArrayList(u8).init(allocator); + var writer = arraylist.writer(); + function.printSourceCode(&writer) catch { + // an error while generating source code + for (symbols.keys()) |key| { + allocator.free(bun.constStrToU8(key)); + } + for (zig_strings) |zig_string| { + allocator.free(bun.constStrToU8(zig_string.slice())); + } + for (symbols.values()) |*function_| { + function_.arg_types.deinit(allocator); + } + symbols.clearAndFree(allocator); + allocator.free(zig_strings); + return ZigString.init("Error while printing code").toErrorInstance(global); + }; + zig_strings[i] = ZigString.init(arraylist.toOwnedSlice()); + } + + const ret = JSC.JSValue.createStringArray(global, zig_strings.ptr, zig_strings.len, true); + + for (symbols.keys()) |key| { + allocator.free(bun.constStrToU8(key)); + } + for (zig_strings) |zig_string| { + allocator.free(bun.constStrToU8(zig_string.slice())); + } + for (symbols.values()) |*function_| { + function_.arg_types.deinit(allocator); + if (function_.step == .compiled) { + allocator.free(function_.step.compiled.buf); + } + } + symbols.clearAndFree(allocator); + + return ret; + } + + // pub fn dlcompile(global: *JSGlobalObject, object: JSC.JSValue) JSValue { + // const allocator = VirtualMachine.vm.allocator; + + // if (object.isEmptyOrUndefinedOrNull() or !object.isObject()) { + // return JSC.toInvalidArguments("Expected an options object with symbol names", .{}, global.ref()); + // } + + // var symbols = std.StringArrayHashMapUnmanaged(Function){}; + // if (generateSymbols(global, &symbols, object) catch JSC.JSValue.zero) |val| { + // // an error while validating symbols + // for (symbols.keys()) |key| { + // allocator.free(bun.constStrToU8(key)); + // } + // symbols.clearAndFree(allocator); + // return val; + // } + + // } + + pub fn open(global: *JSGlobalObject, name_str: ZigString, object: JSC.JSValue) JSC.JSValue { + const allocator = VirtualMachine.vm.allocator; + var name_slice = name_str.toSlice(allocator); + defer name_slice.deinit(); + + if (name_slice.len == 0) { + return JSC.toInvalidArguments("Invalid library name", .{}, global.ref()); + } + + if (object.isEmptyOrUndefinedOrNull() or !object.isObject()) { + return JSC.toInvalidArguments("Expected an options object with symbol names", .{}, global.ref()); + } + + const name = name_slice.sliceZ(); + var symbols = std.StringArrayHashMapUnmanaged(Function){}; + if (generateSymbols(global, &symbols, object) catch JSC.JSValue.zero) |val| { + // an error while validating symbols + for (symbols.keys()) |key| { + allocator.free(bun.constStrToU8(key)); + } + symbols.clearAndFree(allocator); + return val; + } + if (symbols.count() == 0) { + return JSC.toInvalidArguments("Expected at least one symbol", .{}, global.ref()); + } + + var dylib = std.DynLib.open(name) catch { + return JSC.toInvalidArguments("Failed to open library", .{}, global.ref()); + }; + + var obj = JSC.JSValue.c(JSC.C.JSObjectMake(global.ref(), null, null)); + JSC.C.JSValueProtect(global.ref(), obj.asObjectRef()); + defer JSC.C.JSValueUnprotect(global.ref(), obj.asObjectRef()); + for (symbols.values()) |*function| { + var resolved_symbol = dylib.lookup(*anyopaque, function.base_name) orelse { + const ret = JSC.toInvalidArguments("Symbol \"{s}\" not found in \"{s}\"", .{ std.mem.span(function.base_name), name_slice.slice() }, global.ref()); + for (symbols.values()) |*value| { + allocator.free(bun.constStrToU8(std.mem.span(value.base_name))); + value.arg_types.clearAndFree(allocator); + } + symbols.clearAndFree(allocator); + dylib.close(); + return ret; + }; + + function.symbol_from_dynamic_library = resolved_symbol; + function.compile(allocator) catch { + const ret = JSC.toInvalidArguments("Failed to compile symbol \"{s}\" in \"{s}\"", .{ std.mem.span(function.base_name), name_slice.slice() }, global.ref()); + for (symbols.values()) |*value| { + allocator.free(bun.constStrToU8(std.mem.span(value.base_name))); + value.arg_types.clearAndFree(allocator); + } + symbols.clearAndFree(allocator); + dylib.close(); + return ret; + }; + switch (function.step) { + .failed => |err| { + for (symbols.values()) |*value| { + allocator.free(bun.constStrToU8(std.mem.span(value.base_name))); + value.arg_types.clearAndFree(allocator); + } + symbols.clearAndFree(allocator); + dylib.close(); + return ZigString.init(err).toErrorInstance(global); + }, + .pending => { + for (symbols.values()) |*value| { + allocator.free(bun.constStrToU8(std.mem.span(value.base_name))); + value.arg_types.clearAndFree(allocator); + } + symbols.clearAndFree(allocator); + dylib.close(); + return ZigString.init("Failed to compile (nothing happend!)").toErrorInstance(global); + }, + .compiled => |compiled| { + var callback = JSC.C.JSObjectMakeFunctionWithCallback(global.ref(), null, @ptrCast(JSC.C.JSObjectCallAsFunctionCallback, compiled.ptr)); + + obj.put(global, &ZigString.init(std.mem.span(function.base_name)), JSC.JSValue.cast(callback)); + }, + } + } + + var lib = allocator.create(FFI) catch unreachable; + lib.* = .{ + .dylib = dylib, + .functions = symbols, + }; + + var close_object = JSC.JSValue.c(Class.make(global.ref(), lib)); + + return JSC.JSValue.createObject2(global, &ZigString.init("close"), &ZigString.init("symbols"), close_object, obj); + } + pub fn generateSymbols(global: *JSGlobalObject, symbols: *std.StringArrayHashMapUnmanaged(Function), object: JSC.JSValue) !?JSValue { + const allocator = VirtualMachine.vm.allocator; + + var keys = JSC.C.JSObjectCopyPropertyNames(global.ref(), object.asObjectRef()); + defer JSC.C.JSPropertyNameArrayRelease(keys); + const count = JSC.C.JSPropertyNameArrayGetCount(keys); + + try symbols.ensureTotalCapacity(allocator, count); + + var i: usize = 0; + while (i < count) : (i += 1) { + var property_name_ref = JSC.C.JSPropertyNameArrayGetNameAtIndex(keys, i); + defer JSC.C.JSStringRelease(property_name_ref); + const len = JSC.C.JSStringGetLength(property_name_ref); + if (len == 0) continue; + var prop = JSC.C.JSStringGetCharacters8Ptr(property_name_ref)[0..len]; + + var value = JSC.JSValue.c(JSC.C.JSObjectGetProperty(global.ref(), object.asObjectRef(), property_name_ref, null)); + if (value.isEmptyOrUndefinedOrNull()) { + return JSC.toTypeError(JSC.Node.ErrorCode.ERR_INVALID_ARG_VALUE, "Expected an object for key \"{s}\"", .{prop}, global.ref()); + } + + var abi_types = std.ArrayListUnmanaged(ABIType){}; + + if (value.get(global, "params")) |params| { + if (params.isEmptyOrUndefinedOrNull() or !params.jsType().isArray()) { + return ZigString.init("Expected an object with \"params\" as an array").toErrorInstance(global); + } + + var array = params.arrayIterator(global); + + try abi_types.ensureTotalCapacityPrecise(allocator, array.len); + while (array.next()) |val| { + if (val.isEmptyOrUndefinedOrNull() or !val.jsType().isStringLike()) { + abi_types.clearAndFree(allocator); + return ZigString.init("param must be a string (type name)").toErrorInstance(global); + } + + var type_name = val.toSlice(global, allocator); + defer type_name.deinit(); + abi_types.appendAssumeCapacity(ABIType.label.get(type_name.slice()) orelse { + abi_types.clearAndFree(allocator); + return JSC.toTypeError(JSC.Node.ErrorCode.ERR_INVALID_ARG_VALUE, "Unknown type {s}", .{type_name.slice()}, global.ref()); + }); + } + } + // var function + var return_type = ABIType{ .primitive = .@"void" }; + + if (value.get(global, "return_type")) |ret_value| { + var ret_slice = ret_value.toSlice(global, allocator); + defer ret_slice.deinit(); + return_type = ABIType.label.get(ret_slice.slice()) orelse { + abi_types.clearAndFree(allocator); + return JSC.toTypeError(JSC.Node.ErrorCode.ERR_INVALID_ARG_VALUE, "Unknown return type {s}", .{ret_slice.slice()}, global.ref()); + }; + } + + const function = Function{ + .base_name = try allocator.dupeZ(u8, prop), + .arg_types = abi_types, + .return_type = return_type, + }; + symbols.putAssumeCapacity(std.mem.span(function.base_name), function); + } + + return null; + } + + pub const Function = struct { + symbol_from_dynamic_library: ?*anyopaque = null, + base_name: [:0]const u8 = "", + + return_type: ABIType, + arg_types: std.ArrayListUnmanaged(ABIType) = .{}, + step: Step = Step{ .pending = {} }, + + pub const Step = union(enum) { + pending: void, + compiled: struct { + ptr: *anyopaque, + buf: []u8, + }, + failed: []const u8, + }; + + const FFI_HEADER: string = @embedFile("./FFI.h"); + pub inline fn ffiHeader() string { + if (comptime Environment.isDebug) { + var dirpath = std.fs.path.dirname(@src().file).?; + var env = std.process.getEnvMap(default_allocator) catch unreachable; + + const dir = std.mem.replaceOwned( + u8, + default_allocator, + dirpath, + "jarred", + env.get("USER").?, + ) catch unreachable; + var runtime_path = std.fs.path.join(default_allocator, &[_]string{ dir, "FFI.h" }) catch unreachable; + const file = std.fs.openFileAbsolute(runtime_path, .{}) catch @panic("Missing bun/src/javascript/jsc/api/FFI.h."); + defer file.close(); + return file.readToEndAlloc(default_allocator, (file.stat() catch unreachable).size) catch unreachable; + } else { + return FFI_HEADER; + } + } + + pub fn handleTCCError(ctx: ?*anyopaque, message: [*c]const u8) callconv(.C) void { + var this = bun.cast(*Function, ctx.?); + this.step = .{ .failed = std.mem.span(message) }; + } + + extern fn pthread_jit_write_protect_np(enable: bool) callconv(.C) void; + + pub fn compile( + this: *Function, + allocator: std.mem.Allocator, + ) !void { + var source_code = std.ArrayList(u8).init(allocator); + var source_code_writer = source_code.writer(); + try this.printSourceCode(&source_code_writer); + try source_code.append(0); + defer source_code.deinit(); + var state = TCC.tcc_new() orelse return error.TCCMissing; + TCC.tcc_set_error_func(state, this, handleTCCError); + // defer TCC.tcc_delete(state); + _ = TCC.tcc_set_output_type(state, TCC.TCC_OUTPUT_MEMORY); + + const compilation_result = TCC.tcc_compile_string( + state, + source_code.items.ptr, + ); + // did tcc report an error? + if (this.step == .failed) { + return; + } + + // did tcc report failure but never called the error callback? + if (compilation_result == -1) { + this.step = .{ .failed = "tcc returned -1, which means it failed" }; + return; + } + + _ = TCC.tcc_add_symbol(state, this.base_name, this.symbol_from_dynamic_library.?); + + // i don't fully understand this, why it needs two calls + // but that is the API + var relocation_size = TCC.tcc_relocate(state, null); + if (relocation_size > 0) { + var bytes: []u8 = try allocator.rawAlloc(@intCast(usize, relocation_size), 16, 16, 0); + if (comptime Environment.isAarch64 and Environment.isMac) { + pthread_jit_write_protect_np(false); + } + _ = TCC.tcc_relocate(state, bytes.ptr); + if (comptime Environment.isAarch64 and Environment.isMac) { + pthread_jit_write_protect_np(true); + } + if (this.step == .failed) { + allocator.free(bytes); + return; + } + + var formatted_symbol_name = try std.fmt.allocPrintZ(allocator, "bun_gen_{s}", .{std.mem.span(this.base_name)}); + defer allocator.free(formatted_symbol_name); + var symbol = TCC.tcc_get_symbol(state, formatted_symbol_name) orelse { + this.step = .{ .failed = "missing generated symbol in source code" }; + allocator.free(bytes); + + return; + }; + if (this.step == .failed) { + allocator.free(bytes); + return; + } + + this.step = .{ + .compiled = .{ + .ptr = symbol, + .buf = bytes, + }, + }; + return; + } + } + + pub fn printSourceCode( + this: *Function, + writer: anytype, + ) !void { + if (comptime Environment.isRelease) { + try writer.writeAll(std.mem.span(FFI_HEADER)); + } else { + try writer.writeAll(ffiHeader()); + } + + // -- Generate the FFI function symbol + try writer.writeAll("/* --- The Function To Call */\n"); + try this.return_type.typename(writer); + try writer.writeAll(" "); + try writer.writeAll(std.mem.span(this.base_name)); + try writer.writeAll("("); + var first = true; + for (this.arg_types.items) |arg, i| { + if (!first) { + try writer.writeAll(", "); + } + first = false; + try arg.typename(writer); + try writer.print(" arg{d}", .{i}); + } + try writer.writeAll(");\n\n"); + + // -- Generate JavaScriptCore's C wrapper function + try writer.writeAll("/* ---- Your Wrapper Function ---- */\nvoid* bun_gen_"); + try writer.writeAll(std.mem.span(this.base_name)); + try writer.writeAll("(JSContext ctx, EncodedJSValue function, EncodedJSValue thisObject, size_t argumentCount, const EncodedJSValue arguments[], void* exception);\n\n"); + + try writer.writeAll("void* bun_gen_"); + try writer.writeAll(std.mem.span(this.base_name)); + try writer.writeAll("(JSContext ctx, EncodedJSValue function, EncodedJSValue thisObject, size_t argumentCount, const EncodedJSValue arguments[], void* exception) {\n\n"); + var arg_buf: [512]u8 = undefined; + arg_buf[0.."arguments[".len].* = "arguments[".*; + for (this.arg_types.items) |arg, i| { + try writer.writeAll(" "); + try arg.typename(writer); + var printed = std.fmt.bufPrintIntToSlice(arg_buf["arguments[".len..], i, 10, .lower, .{}); + arg_buf["arguments[".len + printed.len] = ']'; + try writer.print(" arg{d} = {};\n", .{ i, arg.toC(arg_buf[0 .. printed.len + "arguments[]".len]) }); + } + + try writer.writeAll(" "); + if (!(this.return_type == .primitive and this.return_type.primitive == .void)) { + try this.return_type.typename(writer); + try writer.writeAll(" return_value = "); + } + try writer.print("{s}(", .{std.mem.span(this.base_name)}); + first = true; + for (this.arg_types.items) |_, i| { + if (!first) { + try writer.writeAll(", "); + } + first = false; + try writer.print("arg{d}", .{i}); + } + try writer.writeAll(");\n\n"); + + try writer.writeAll(" "); + + try writer.writeAll("return "); + + if (!(this.return_type == .primitive and this.return_type.primitive == .void)) { + try writer.print("{}.asPtr", .{this.return_type.toJS("return_value")}); + } else { + try writer.writeAll("ValueUndefined.asPtr"); + } + + try writer.writeAll(";\n}\n\n"); + } + }; + + pub const ABIType = union(enum) { + primitive: Primitive.Tag, + pointer: Pointer, + + pub const label = ComptimeStringMap( + ABIType, + .{ + .{ "char", ABIType{ .primitive = Primitive.Tag.char } }, + .{ "bool", ABIType{ .primitive = Primitive.Tag.@"bool" } }, + + .{ "i8", ABIType{ .primitive = Primitive.Tag.int8_t } }, + .{ "u8", ABIType{ .primitive = Primitive.Tag.uint8_t } }, + .{ "i16", ABIType{ .primitive = Primitive.Tag.int16_t } }, + .{ "int", ABIType{ .primitive = Primitive.Tag.int32_t } }, + .{ "c_int", ABIType{ .primitive = Primitive.Tag.int32_t } }, + .{ "c_uint", ABIType{ .primitive = Primitive.Tag.uint32_t } }, + .{ "i32", ABIType{ .primitive = Primitive.Tag.int32_t } }, + .{ "i64", ABIType{ .primitive = Primitive.Tag.int64_t } }, + .{ "u16", ABIType{ .primitive = Primitive.Tag.uint16_t } }, + .{ "u32", ABIType{ .primitive = Primitive.Tag.uint32_t } }, + .{ "u64", ABIType{ .primitive = Primitive.Tag.uint64_t } }, + .{ "int8_t", ABIType{ .primitive = Primitive.Tag.int8_t } }, + .{ "isize", ABIType{ .primitive = Primitive.Tag.int64_t } }, + .{ "usize", ABIType{ .primitive = Primitive.Tag.uint64_t } }, + .{ "int16_t", ABIType{ .primitive = Primitive.Tag.int16_t } }, + .{ "int32_t", ABIType{ .primitive = Primitive.Tag.int32_t } }, + .{ "int64_t", ABIType{ .primitive = Primitive.Tag.int64_t } }, + .{ "uint8_t", ABIType{ .primitive = Primitive.Tag.uint8_t } }, + .{ "uint16_t", ABIType{ .primitive = Primitive.Tag.uint16_t } }, + .{ "uint32_t", ABIType{ .primitive = Primitive.Tag.uint32_t } }, + .{ "uint64_t", ABIType{ .primitive = Primitive.Tag.uint64_t } }, + + .{ "char*", ABIType{ .pointer = .{ .primitive = Primitive.Tag.char } } }, + .{ "void*", ABIType{ .pointer = .{ .primitive = Primitive.Tag.@"void" } } }, + .{ "const char*", ABIType{ .pointer = .{ .is_const = true, .primitive = Primitive.Tag.char } } }, + .{ "const void*", ABIType{ .pointer = .{ .is_const = true, .primitive = Primitive.Tag.@"void" } } }, + }, + ); + + const ToJSFormatter = struct { + symbol: []const u8, + abi: ABIType, + + pub fn format(self: ToJSFormatter, comptime fmt: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void { + switch (self.abi) { + .pointer => |ptr| { + _ = ptr; + }, + .primitive => |prim| { + try prim.toJS(self.symbol).format(comptime fmt, opts, writer); + }, + } + } + }; + + const ToCFormatter = struct { + symbol: []const u8, + abi: ABIType, + + pub fn format(self: ToCFormatter, comptime fmt: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void { + try self.abi.primitive.toC(self.symbol).format( + comptime fmt, + opts, + writer, + ); + } + }; + + pub fn toJS( + this: ABIType, + symbol: string, + ) ToJSFormatter { + return ToJSFormatter{ + .symbol = symbol, + .abi = this, + }; + } + + pub fn toC(this: ABIType, symbol: string) ToCFormatter { + return ToCFormatter{ + .symbol = symbol, + .abi = this, + }; + } + + pub fn typename(this: ABIType, writer: anytype) !void { + switch (this) { + .primitive => |prim| { + try writer.writeAll(prim.typename()); + }, + .pointer => |ptr| { + try ptr.typename(writer); + }, + } + } + }; + + pub const Pointer = struct { + count: u8 = 1, + primitive: Primitive.Tag, + is_const: bool = false, + + pub fn typename(this: Pointer, writer: anytype) !void { + if (this.is_const) { + try writer.writeAll("const "); + } + + var i: u8 = 0; + while (i < this.count) { + try writer.writeAll("*"); + i = i + 1; + } + + try writer.writeAll(" "); + try writer.writeAll(this.primitive.typename()); + } + }; + + pub const Primitive = union(Tag) { + char: i8, + int8_t: i8, + uint8_t: u8, + + int16_t: i16, + uint16_t: u16, + + int32_t: c_int, + uint32_t: c_uint, + + int64_t: i64, + uint64_t: u64, + + double: f64, + float: f32, + + void: *anyopaque, + + bool: bool, + + dynamic: struct { + size: u32, + alignment: u21, + name: []const u8, + }, + + pub const Tag = enum(i32) { + char = 0, + + int8_t = 1, + uint8_t = 2, + + int16_t = 3, + uint16_t = 4, + + int32_t = 5, + uint32_t = 6, + + int64_t = 7, + uint64_t = 8, + + double = 9, + float = 10, + + void = 11, + dynamic = 12, + + bool = 13, + + const ToCFormatter = struct { + symbol: string, + tag: Tag, + + pub fn format(self: ToCFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + switch (self.tag) { + .void => {}, + .bool => { + try writer.print("JSVALUE_IS_TRUE({s})", .{self.symbol}); + }, + .char, .int8_t, .uint8_t, .int16_t, .uint16_t, .int32_t, .uint32_t => { + try writer.print("JSVALUE_TO_INT32({s})", .{self.symbol}); + }, + .int64_t => {}, + .uint64_t => {}, + .double => { + try writer.print("JSVALUE_TO_DOUBLE({s})", .{self.symbol}); + }, + .float => { + try writer.print("JSVALUE_TO_FLOAT({s})", .{self.symbol}); + }, + else => unreachable, + } + } + }; + + const ToJSFormatter = struct { + symbol: []const u8, + tag: Tag, + + pub fn format(self: ToJSFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + switch (self.tag) { + .void => {}, + .bool => { + try writer.print("BOOLEAN_TO_JSVALUE({s})", .{self.symbol}); + }, + .int8_t, .uint8_t, .int16_t, .uint16_t, .int32_t, .uint32_t => { + try writer.print("INT32_TO_JSVALUE({s})", .{self.symbol}); + }, + .int64_t => {}, + .uint64_t => {}, + .double => { + try writer.print("DOUBLE_to_JSVALUE({s})", .{self.symbol}); + }, + .float => { + try writer.print("FLOAT_to_JSVALUE({s})", .{self.symbol}); + }, + else => unreachable, + } + } + }; + + pub fn toC(this: Tag, symbol: string) ToCFormatter { + return ToCFormatter{ .tag = this, .symbol = symbol }; + } + + pub fn toJS( + this: Tag, + symbol: string, + ) ToJSFormatter { + return ToJSFormatter{ + .tag = this, + .symbol = symbol, + }; + } + + pub fn typename(this: Tag) []const u8 { + return switch (this) { + .void => "void", + .bool => "bool", + .int8_t => "int8_t", + .uint8_t => "uint8_t", + .int16_t => "int16_t", + .uint16_t => "uint16_t", + .int32_t => "int32_t", + .uint32_t => "uint32_t", + .int64_t => "int64_t", + .uint64_t => "uint64_t", + .double => "float", + .float => "double", + .char => "int8_t", + else => unreachable, + }; + } + }; + }; +}; diff --git a/src/javascript/jsc/api/libtcc1.a.macos-aarch64 b/src/javascript/jsc/api/libtcc1.a.macos-aarch64 new file mode 100644 index 0000000000000000000000000000000000000000..60696b61176ee2c2bd97bbc379b073c6e24b0061 GIT binary patch literal 29988 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 a<80>RHcP)9*B$8w`Gd5~U!vc5{r>|V@eRuW literal 0 HcmV?d00001 diff --git a/src/javascript/jsc/base.zig b/src/javascript/jsc/base.zig index 3db5c01107..7abbe13432 100644 --- a/src/javascript/jsc/base.zig +++ b/src/javascript/jsc/base.zig @@ -2568,6 +2568,7 @@ const SHA384 = JSC.API.Bun.Crypto.SHA384; const SHA256 = JSC.API.Bun.Crypto.SHA256; const SHA512_256 = JSC.API.Bun.Crypto.SHA512_256; const MD5_SHA1 = JSC.API.Bun.Crypto.MD5_SHA1; +const FFI = JSC.FFI; pub const JSPrivateDataPtr = TaggedPointerUnion(.{ AttributeIterator, @@ -2614,6 +2615,7 @@ pub const JSPrivateDataPtr = TaggedPointerUnion(.{ TextEncoder, TimeoutTask, Transpiler, + FFI, }); pub inline fn GetJSPrivateData(comptime Type: type, ref: js.JSObjectRef) ?*Type { diff --git a/src/javascript/jsc/bindings/bindings.zig b/src/javascript/jsc/bindings/bindings.zig index 2643abfed9..840f9025e0 100644 --- a/src/javascript/jsc/bindings/bindings.zig +++ b/src/javascript/jsc/bindings/bindings.zig @@ -141,6 +141,10 @@ pub const ZigString = extern struct { return this.ptr[0..this.len]; } + pub fn sliceZ(this: Slice) [:0]const u8 { + return std.meta.assumeSentinel(this.ptr[0..this.len], 0); + } + pub fn mut(this: Slice) []u8 { return @intToPtr([*]u8, @ptrToInt(this.ptr))[0..this.len]; } @@ -3484,3 +3488,11 @@ pub const WTF = struct { pub const Callback = struct { // zig: Value, }; + +const NodeBuffer = @import("../node/buffer.zig"); + +comptime { + if (!JSC.is_bindgen) { + std.testing.refAllDecls(NodeBuffer.Write); + } +}