Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion tslang/test/tester/defaultlib-collector.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
# a user shared library (docs/single-gc-collector-design.md). This drives tslang with the real
# default library instead:
#
# MODE=jit the JIT, the program alone and importing a shared library
# MODE=jit the JIT, the program alone and importing a shared library; on Linux also without
# the runtime passed in --shared-libs
# MODE=compile an exe alone, and an exe importing a shared library that links the default-library DLL
#
# The default library is a separate build (TypeScriptCompilerDefaultLib). With none found the test
Expand Down Expand Up @@ -131,6 +132,13 @@ if(MODE STREQUAL "jit")
"${TSLANG}" --emit=jit ${common} "--shared-libs=${runtime}" "${alone}")
run_program("JIT importing a shared library, default library" "${WORK_DIR}"
"${TSLANG}" --emit=jit ${common} "--shared-libs=${runtime}" "${program}")
# The runtime found by tslang itself (--tslang-lib-path), as a user runs it. On Linux the
# default library takes GC_* from the process, so tslang has to load the runtime first; one
# passed with --shared-libs is ahead of it anyway, which is why the runs above never failed.
if(NOT WIN32)
run_program("JIT, default library, runtime not passed" "${WORK_DIR}/alone"
"${TSLANG}" --emit=jit ${common} "${alone}")
endif()
elseif(MODE STREQUAL "compile")
run("--emit=exe alone, default library" "${WORK_DIR}/alone"
"${TSLANG}" --emit=exe ${common} "${alone}" -o "alone${exe_suffix}")
Expand Down
16 changes: 12 additions & 4 deletions tslang/tslang/jit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -593,13 +593,14 @@ static int prepareJitProcess(CompileOptions &compileOptions, bool nativeImage)
// If shared library implements custom mlir-runner library init and destroy
// functions, we'll use them to register the library with the execution
// engine. Otherwise we'll pass library directly to the execution engine.
std::string defaultLibFile;
if (!compileOptions.noDefaultLib && !nativeImage)
{
// per-build subfolder (debug/release) must match the JIT compilation mode.
// Keyed on --di (generate debug info): with debug info use the debug lib.
// ...and per memory model, for the same reason the linker path is: the default lib
// allocates the way the model it was built for allocates. See getDefaultLibSubDir.
auto defaultLibFile = getDefaultLibBinary(/*shared=*/true, compileOptions,
defaultLibFile = getDefaultLibBinary(/*shared=*/true, compileOptions,
llvm::Triple(llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()))); // JIT is host-only

// Named here rather than left to the loader, for the reason exe.cpp checks the link
Expand Down Expand Up @@ -629,9 +630,7 @@ static int prepareJitProcess(CompileOptions &compileOptions, bool nativeImage)
return -1;
}
#endif

clSharedLibs.push_back(defaultLibFile);
}
}

// add default libs in case they are not part of options
#ifdef WIN32
Expand Down Expand Up @@ -685,6 +684,15 @@ static int prepareJitProcess(CompileOptions &compileOptions, bool nativeImage)
}
}

// After the runtime: on Linux the default library leaves GC_* undefined and takes them from
// the process (a collector of its own would be a second one), so they have to be loaded
// before it is, or dlopen fails on GC_malloc. A runtime passed with --shared-libs is
// already ahead of it.
if (!defaultLibFile.empty())
{
clSharedLibs.push_back(defaultLibFile);
}

#ifdef _WIN32
// tslang.exe links the CRT statically (/MT[d]), so its libc symbols are not in
// any DLL export table. The JIT's process-symbol resolver would otherwise bind
Expand Down
Loading