diff --git a/doc/source/reference/embedding/c_api.rst b/doc/source/reference/embedding/c_api.rst index 380d627149..513f93a3c5 100644 --- a/doc/source/reference/embedding/c_api.rst +++ b/doc/source/reference/embedding/c_api.rst @@ -185,6 +185,13 @@ File access ``das_fileaccess_introduce_native_module(access, req)`` / ``das_fileaccess_introduce_native_module_n(access, req, req_length)`` Pre-loads one native module by its require-style path. +``das_fileaccess_add_extra_module(access, module_name, module_file)`` / ``das_fileaccess_add_extra_module_n(...)`` + Registers a module as an implicit dependency of every program compiled + through this file access, as if each program had a ``require`` for it. + This is how the daslang CLI injects daslib support modules: + ``just_in_time`` (``-jit``), ``debug`` (``-debugger``), ``profiler`` + (``-profiler``). + ``das_fileaccess_lock(access)`` / ``das_fileaccess_unlock(access)`` While locked, only pre-introduced files can be accessed — filesystem reads are blocked. Essential for sandboxing. @@ -195,6 +202,13 @@ File access ``das_get_root_n(buf, maxbuf)`` ``size_t``-sized counterpart. Passing ``NULL, 0`` is valid. +``das_set_root(root)`` / ``das_set_root_n(root, root_length)`` + Sets the daslang root path. When unset, the root is derived from the + host executable's location (walking up past ``bin/``), which is wrong + for embedded applications that live outside the daslang distribution — + call this before creating file access objects so ``daslib/``, + ``modules/`` and ``lib/`` resolve. + Compilation =========== @@ -291,6 +305,14 @@ Compilation policies - Generate extended RTTI * - ``DAS_POLICY_NO_OPTIMIZATIONS`` - Disable all optimizations + * - ``DAS_POLICY_JIT_ENABLED`` + - Enable JIT compilation (see *Enabling JIT* below) + * - ``DAS_POLICY_JIT_DLL_MODE`` + - With JIT: cache generated code as per-script DLLs under + ``/.jitted_scripts`` (default: on); off = in-memory codegen + every run, no cache writes. The cache path needs a DLL build of + daslang — a static-linked host always codegens in-memory regardless + of this flag **Integer policies** (``das_int_policy``): @@ -313,6 +335,38 @@ Compilation policies See :ref:`tutorial_integration_c_sandbox`. +Enabling JIT +------------ + +The CLI's ``-jit`` switch is three host-side steps; an embedded host mirrors +them through the C API. The daslang root must point at a distribution that +carries ``daslib/``, ``modules/dasLLVM`` and ``lib/`` (the LLVM backend +library) — set it explicitly when the host executable lives elsewhere. +Script-side ``options jit_enabled = true`` has no effect: JIT is a host +policy. + +.. code-block:: c + + das_set_root("/path/to/daslang"); /* unless the exe sits in /bin */ + + das_file_access * fa = das_fileaccess_make_default(); + das_register_dynamic_modules(fa, "/path/to/daslang", NULL, 0, tout); + + char root[4096], jit_mod[4200]; + das_get_root_n(root, sizeof(root)); + snprintf(jit_mod, sizeof(jit_mod), "%s/daslib/just_in_time.das", root); + das_fileaccess_add_extra_module(fa, "just_in_time", jit_mod); + + das_policies * pol = das_policies_make(); + das_policies_set_bool(pol, DAS_POLICY_JIT_ENABLED, 1); + + das_program * prog = das_program_compile_policies( + "script.das", fa, tout, lib, pol); + +After ``das_program_simulate()`` the ``[jit]`` functions run natively; +``jit_enabled()`` returns ``true`` inside the script. + + Simulation and context ====================== diff --git a/include/daScript/daScriptC.h b/include/daScript/daScriptC.h index 883dede5ea..8bb2007147 100644 --- a/include/daScript/daScriptC.h +++ b/include/daScript/daScriptC.h @@ -267,6 +267,17 @@ DAS_CC_API void das_fileaccess_introduce_native_modules ( das_file_access * acce DAS_CC_API int das_fileaccess_introduce_native_module ( das_file_access * access, const char * req ); DAS_CC_API int das_fileaccess_introduce_native_module_n ( das_file_access * access, const char * req, size_t req_length ); +// Register a module as an implicit dependency of every program compiled through +// this file access, as if each program had a 'require' for it. This is how the +// daslang CLI injects daslib support modules: "just_in_time" ('-jit'), +// "debug" ('-debugger'), "profiler" ('-profiler'). +// 'module_name' is the require name; 'module_file' is the path to its source +// (e.g. "/daslib/just_in_time.das"). +DAS_CC_API void das_fileaccess_add_extra_module ( das_file_access * access, const char * module_name, const char * module_file ); +DAS_CC_API void das_fileaccess_add_extra_module_n ( das_file_access * access, + const char * module_name, size_t module_name_length, + const char * module_file, size_t module_file_length ); + // Lock the file access. While locked, getNewFileInfo() returns NULL for all // files not already in the cache, so only pre-introduced files can be accessed. DAS_CC_API void das_fileaccess_lock ( das_file_access * access ); @@ -280,6 +291,13 @@ DAS_CC_API int das_fileaccess_is_locked ( das_file_access * access ); DAS_CC_API void das_get_root ( char * root, int maxbuf ); DAS_CC_API void das_get_root_n ( char * root, size_t maxbuf ); +// Set the daslang root path. When unset, the root is derived from the host +// executable's location (walking up past bin/), which is wrong for embedded +// applications that live outside the daslang distribution - call this before +// creating file access objects so daslib/, modules/ and lib/ resolve. +DAS_CC_API void das_set_root ( const char * root ); +DAS_CC_API void das_set_root_n ( const char * root, size_t root_length ); + // --- Compilation --- // Compile a daslang program from the file at 'program_file'. @@ -787,7 +805,9 @@ typedef enum das_bool_policy { DAS_POLICY_LOG_OPTIMIZATION_PASSES, // Log the AST after every optimizer pass (verbose) DAS_POLICY_FUSION, // Fuse interpreter nodes into wider superinstructions at simulate time (default: on) DAS_POLICY_AUTO_INLINE_FUNCTIONS, // Heuristic best-effort inlining of plain calls and operator sites of small same-module [inline]-shaped functions (default ON; silent declines; optimized builds only; cross-module inlining stays the explicit [inline] contract) - DAS_POLICY_DISABLE_TEMP_STRING_RECLAIM // Disable the temp-string reclaim pass (fresh-string call results riding the 1-slot dispose queue) + DAS_POLICY_DISABLE_TEMP_STRING_RECLAIM, // Disable the temp-string reclaim pass (fresh-string call results riding the 1-slot dispose queue) + DAS_POLICY_JIT_ENABLED, // Enable JIT compilation of [jit] functions. The flag alone is not enough: the host must also register the "just_in_time" extra module (see das_fileaccess_add_extra_module) so the LLVM JIT backend is compiled in + DAS_POLICY_JIT_DLL_MODE // With JIT: cache generated code as per-script DLLs under /.jitted_scripts (default: on). Off = codegen in-memory every run, no cache writes. The cache path needs a DLL build of daslang; a static-linked host always codegens in-memory regardless of this flag } das_bool_policy; // Integer policy fields (stack size, heap limits). diff --git a/include/daScript/simulate/aot_builtin_ast.h b/include/daScript/simulate/aot_builtin_ast.h index 7a2e3e60b4..942d85a505 100644 --- a/include/daScript/simulate/aot_builtin_ast.h +++ b/include/daScript/simulate/aot_builtin_ast.h @@ -453,6 +453,8 @@ namespace das { DAS_CC_API void addModuleLintMacro ( Module * module, PassMacroPtr _newM, Context * ); DAS_CC_API void addModuleGlobalLintMacro ( Module * module, PassMacroPtr _newM, Context * ); DAS_CC_API void addModuleOptimizationMacro ( Module * module, PassMacroPtr _newM, Context * ); + DAS_CC_API void addModulePostRewriteMacro ( Module * module, PassMacroPtr _newM, Context * ); + DAS_CC_API void addModulePostCompileMacro ( Module * module, PassMacroPtr _newM, Context * ); DAS_CC_API VariantMacroPtr makeVariantMacro ( const char * name, const void * pClass, const StructInfo * info, Context * context ); DAS_CC_API void addModuleVariantMacro ( Module * module, VariantMacroPtr newM, Context * context ); DAS_CC_API ForLoopMacroPtr makeForLoopMacro ( const char * name, const void * pClass, const StructInfo * info, Context * context ); diff --git a/modules/dasGlsl/CMakeLists.txt b/modules/dasGlsl/CMakeLists.txt index acddfa3d63..83ab415222 100644 --- a/modules/dasGlsl/CMakeLists.txt +++ b/modules/dasGlsl/CMakeLists.txt @@ -5,6 +5,12 @@ IF(NOT DAS_GLSL_INCLUDED) ADD_MODULE_DAS_FROM_DESCRIPTOR(glsl glsl) ADD_MODULE_DAS_FROM_DESCRIPTOR(geometry glsl) + # runtime-callable module code the AOT suite must carry stubs for (glsl_* stays out: + # emission-side macro code, nothing calls it at runtime) + SET(DASGLSL_AOT_FILES + modules/dasGlsl/glsl/geom_gen.das +) + install(DIRECTORY ${PROJECT_SOURCE_DIR}/modules/dasGlsl/glsl DESTINATION ${DAS_INSTALL_MODULESDIR}/dasGlsl FILES_MATCHING diff --git a/modules/dasLLVM/daslib/llvm_jit.das b/modules/dasLLVM/daslib/llvm_jit.das index d95010a646..fb3f1c0d2a 100644 --- a/modules/dasLLVM/daslib/llvm_jit.das +++ b/modules/dasLLVM/daslib/llvm_jit.das @@ -7583,7 +7583,7 @@ def private get_llvm_function_type(func : FunctionPtr; types : PrimitiveTypes?) } [macro_function] -def private add_ctor_dtor_function(ctor_dtor : array>; types : PrimitiveTypes?) { +def private add_ctor_dtor_function(ctor_dtor : array>; types : PrimitiveTypes?; skip_dtors : bool) { let priority = 0 |> uint64() let dataPointerType = LLVMPointerType(types.t_int8, 0u) let funcType = LLVMPointerType(LLVMFunctionType(types.t_void, null, 0u, 0), 0u) @@ -7635,7 +7635,7 @@ def private add_ctor_dtor_function(ctor_dtor : array