Skip to content

Commit 628209c

Browse files
separate codegen/LLVM from julia runtime (#41936)
separate libjulia-internal and libjulia-codegen makes codegen optional via a plugin interface Add special `@` character to `LOADER_BUILD_DEP_LIBS` and friends This allows us to mark a library as `"special"` so that the loader doesn't attempt to open it blindly, but rather interprets it as a list of positional arguments, that it knows how to interpret. We strictly require exactly the number of special libraries, to help avoid errors in the future as we add to this list. Strip windows runtime symbols from the windows import library Without stripping these symbols out of the import library, we end up with duplicate symbol definition errors. Co-authored-by: Julian Samaroo <jpsamaroo@jpsamaroo.me> Co-authored-by: Elliot Saba <staticfloat@gmail.com>
1 parent 153db7a commit 628209c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+1411
-1114
lines changed

Make.inc

+15-5
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,7 @@ OPENBLAS_DYNAMIC_ARCH:=0
935935
OPENBLAS_TARGET_ARCH:=ARMV8
936936
USE_BLAS64:=1
937937
BINARY:=64
938+
HAVE_SSP:=1
938939
ifeq ($(OS),Darwin)
939940
# Apple Chips are all at least A12Z
940941
MCPU:=apple-a12
@@ -1500,6 +1501,12 @@ LIBJULIAINTERNAL_INSTALL_DEPLIB := $(call dep_lib_path,$(libdir),$(private_shlib
15001501
LIBJULIAINTERNAL_DEBUG_BUILD_DEPLIB := $(call dep_lib_path,$(build_libdir),$(build_shlibdir)/libjulia-internal-debug.$(JL_MAJOR_SHLIB_EXT))
15011502
LIBJULIAINTERNAL_DEBUG_INSTALL_DEPLIB := $(call dep_lib_path,$(libdir),$(private_shlibdir)/libjulia-internal-debug.$(JL_MAJOR_SHLIB_EXT))
15021503

1504+
LIBJULIACODEGEN_BUILD_DEPLIB := $(call dep_lib_path,$(build_libdir),$(build_shlibdir)/libjulia-codegen.$(JL_MAJOR_SHLIB_EXT))
1505+
LIBJULIACODEGEN_INSTALL_DEPLIB := $(call dep_lib_path,$(libdir),$(private_shlibdir)/libjulia-codegen.$(JL_MAJOR_SHLIB_EXT))
1506+
1507+
LIBJULIACODEGEN_DEBUG_BUILD_DEPLIB := $(call dep_lib_path,$(build_libdir),$(build_shlibdir)/libjulia-codegen-debug.$(JL_MAJOR_SHLIB_EXT))
1508+
LIBJULIACODEGEN_DEBUG_INSTALL_DEPLIB := $(call dep_lib_path,$(libdir),$(private_shlibdir)/libjulia-codegen-debug.$(JL_MAJOR_SHLIB_EXT))
1509+
15031510
ifeq ($(OS),WINNT)
15041511
ifeq ($(BINARY),32)
15051512
LIBGCC_NAME := libgcc_s_sjlj-1.$(SHLIB_EXT)
@@ -1539,16 +1546,19 @@ LIBM_INSTALL_DEPLIB := $(call dep_lib_path,$(libdir),$(private_shlibdir)/$(LIBMN
15391546
# We list:
15401547
# * libgcc_s, because FreeBSD needs to load ours, not the system one.
15411548
# * libopenlibm, because Windows has an untrustworthy libm, and we want to use ours more than theirs
1542-
# * libjulia, which must always come last.
1549+
# * libjulia-internal, which must always come second-to-last.
1550+
# * libjulia-codegen, which must always come last
15431551
#
15441552
# We need these four separate variables because:
15451553
# * debug builds must link against libjuliadebug, not libjulia
15461554
# * install time relative paths are not equal to build time relative paths (../lib vs. ../lib/julia)
15471555
# That second point will no longer be true for most deps once they are placed within Artifacts directories.
1548-
LOADER_BUILD_DEP_LIBS = $(LIBGCC_BUILD_DEPLIB):$(LIBM_BUILD_DEPLIB):$(LIBJULIAINTERNAL_BUILD_DEPLIB)
1549-
LOADER_DEBUG_BUILD_DEP_LIBS = $(LIBGCC_BUILD_DEPLIB):$(LIBM_BUILD_DEPLIB):$(LIBJULIAINTERNAL_DEBUG_BUILD_DEPLIB)
1550-
LOADER_INSTALL_DEP_LIBS = $(LIBGCC_INSTALL_DEPLIB):$(LIBM_INSTALL_DEPLIB):$(LIBJULIAINTERNAL_INSTALL_DEPLIB)
1551-
LOADER_DEBUG_INSTALL_DEP_LIBS = $(LIBGCC_INSTALL_DEPLIB):$(LIBM_INSTALL_DEPLIB):$(LIBJULIAINTERNAL_DEBUG_INSTALL_DEPLIB)
1556+
# Note that we prefix `libjulia-codegen` and `libjulia-internal` with `@` to signify to the loader that it
1557+
# should not automatically dlopen() it in its loading loop.
1558+
LOADER_BUILD_DEP_LIBS = $(LIBGCC_BUILD_DEPLIB):$(LIBM_BUILD_DEPLIB):@$(LIBJULIAINTERNAL_BUILD_DEPLIB):@$(LIBJULIACODEGEN_BUILD_DEPLIB):
1559+
LOADER_DEBUG_BUILD_DEP_LIBS = $(LIBGCC_BUILD_DEPLIB):$(LIBM_BUILD_DEPLIB):@$(LIBJULIAINTERNAL_DEBUG_BUILD_DEPLIB):@$(LIBJULIACODEGEN_DEBUG_BUILD_DEPLIB):
1560+
LOADER_INSTALL_DEP_LIBS = $(LIBGCC_INSTALL_DEPLIB):$(LIBM_INSTALL_DEPLIB):@$(LIBJULIAINTERNAL_INSTALL_DEPLIB):@$(LIBJULIACODEGEN_INSTALL_DEPLIB):
1561+
LOADER_DEBUG_INSTALL_DEP_LIBS = $(LIBGCC_INSTALL_DEPLIB):$(LIBM_INSTALL_DEPLIB):@$(LIBJULIAINTERNAL_DEBUG_INSTALL_DEPLIB):@$(LIBJULIACODEGEN_DEBUG_INSTALL_DEPLIB):
15521562

15531563
# Colors for make
15541564
ifndef VERBOSE

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,9 @@ JL_TARGETS += julia-debug
165165
endif
166166

167167
# private libraries, that are installed in $(prefix)/lib/julia
168-
JL_PRIVATE_LIBS-0 := libccalltest libllvmcalltest libjulia-internal libblastrampoline
168+
JL_PRIVATE_LIBS-0 := libccalltest libllvmcalltest libjulia-internal libjulia-codegen libblastrampoline
169169
ifeq ($(BUNDLE_DEBUG_LIBS),1)
170-
JL_PRIVATE_LIBS-0 += libjulia-internal-debug
170+
JL_PRIVATE_LIBS-0 += libjulia-internal-debug libjulia-codegen-debug
171171
endif
172172
ifeq ($(USE_GPL_LIBS), 1)
173173
JL_PRIVATE_LIBS-$(USE_SYSTEM_LIBSUITESPARSE) += libamd libbtf libcamd libccolamd libcholmod libcolamd libklu libldl librbio libspqr libsuitesparseconfig libumfpack

NEWS.md

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ Language changes
2424
Compiler/Runtime improvements
2525
-----------------------------
2626

27+
* The LLVM-based compiler has been separated from the run-time library into a new library,
28+
`libjulia-codegen`. It is loaded by default, so normal usage should see no changes.
29+
In deployments that do not need the compiler (e.g. system images where all needed code
30+
is precompiled), this library (and its LLVM dependency) can simply be excluded ([#41936]).
2731

2832
Command-line option changes
2933
---------------------------

cli/jl_exports.h

+30-10
Original file line numberDiff line numberDiff line change
@@ -19,37 +19,57 @@ JL_EXPORTED_DATA_SYMBOLS(XX)
1919
// Declare list of exported functions (sans type)
2020
#define XX(name) JL_DLLEXPORT void name(void);
2121
typedef void (anonfunc)(void);
22-
JL_EXPORTED_FUNCS(XX)
22+
JL_RUNTIME_EXPORTED_FUNCS(XX)
2323
#ifdef _OS_WINDOWS_
24-
JL_EXPORTED_FUNCS_WIN(XX)
24+
JL_RUNTIME_EXPORTED_FUNCS_WIN(XX)
2525
#endif
26+
JL_CODEGEN_EXPORTED_FUNCS(XX)
2627
#undef XX
2728

2829
// Define holder locations for function addresses as `const void * $(name)_addr = NULL;
2930
#define XX(name) JL_HIDDEN anonfunc * name##_addr = NULL;
30-
JL_EXPORTED_FUNCS(XX)
31+
JL_RUNTIME_EXPORTED_FUNCS(XX)
3132
#ifdef _OS_WINDOWS_
32-
JL_EXPORTED_FUNCS_WIN(XX)
33+
JL_RUNTIME_EXPORTED_FUNCS_WIN(XX)
3334
#endif
35+
JL_CODEGEN_EXPORTED_FUNCS(XX)
3436
#undef XX
3537

3638
// Generate lists of function names and addresses
3739
#define XX(name) "i" #name,
38-
static const char *const jl_exported_func_names[] = {
39-
JL_EXPORTED_FUNCS(XX)
40+
static const char *const jl_runtime_exported_func_names[] = {
41+
JL_RUNTIME_EXPORTED_FUNCS(XX)
4042
#ifdef _OS_WINDOWS_
41-
JL_EXPORTED_FUNCS_WIN(XX)
43+
JL_RUNTIME_EXPORTED_FUNCS_WIN(XX)
4244
#endif
4345
NULL
4446
};
4547
#undef XX
4648

49+
#define XX(name) #name"_impl",
50+
static const char *const jl_codegen_exported_func_names[] = {
51+
JL_CODEGEN_EXPORTED_FUNCS(XX)
52+
NULL
53+
};
54+
#undef XX
55+
56+
#define XX(name) #name"_fallback",
57+
static const char *const jl_codegen_fallback_func_names[] = {
58+
JL_CODEGEN_EXPORTED_FUNCS(XX)
59+
NULL
60+
};
61+
#undef XX
62+
4763
#define XX(name) &name##_addr,
48-
static anonfunc **const jl_exported_func_addrs[] = {
49-
JL_EXPORTED_FUNCS(XX)
64+
static anonfunc **const jl_runtime_exported_func_addrs[] = {
65+
JL_RUNTIME_EXPORTED_FUNCS(XX)
5066
#ifdef _OS_WINDOWS_
51-
JL_EXPORTED_FUNCS_WIN(XX)
67+
JL_RUNTIME_EXPORTED_FUNCS_WIN(XX)
5268
#endif
5369
NULL
5470
};
71+
static anonfunc **const jl_codegen_exported_func_addrs[] = {
72+
JL_CODEGEN_EXPORTED_FUNCS(XX)
73+
NULL
74+
};
5575
#undef XX

cli/list_strip_symbols.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
#include "jl_exported_funcs.inc"
44
#include "trampolines/common.h"
55
#define XX(x) --strip-symbol=CNAME(x)
6-
JL_EXPORTED_FUNCS(XX)
6+
JL_RUNTIME_EXPORTED_FUNCS(XX)
77
#ifdef _OS_WINDOWS_
8-
JL_EXPORTED_FUNCS_WIN(XX)
8+
JL_RUNTIME_EXPORTED_FUNCS_WIN(XX)
99
#endif
1010
#undef XX

cli/loader.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,19 @@
2525
#include <stdint.h>
2626

2727
#ifdef _OS_WINDOWS_
28+
2829
#define WIN32_LEAN_AND_MEAN
2930
#include <windows.h>
31+
3032
#else
33+
3134
#ifdef _OS_DARWIN_
3235
#include <mach-o/dyld.h>
3336
#endif
3437
#ifdef _OS_FREEBSD_
3538
#include <stddef.h>
3639
#include <sys/sysctl.h>
3740
#endif
38-
3941
#define _GNU_SOURCE // Need this for `dladdr()`
4042
#include <stdio.h>
4143
#include <stdlib.h>
@@ -44,6 +46,7 @@
4446
#include <libgen.h>
4547
#include <unistd.h>
4648
#include <dlfcn.h>
49+
4750
#endif
4851

4952
// Borrow definition from `support/dtypes.h`

cli/loader_lib.c

+57-11
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ extern "C" {
1616
#endif
1717

1818
// Save DEP_LIBS to a variable that is explicitly sized for expansion
19-
static char dep_libs[512] = DEP_LIBS;
19+
static char dep_libs[1024] = DEP_LIBS;
2020

2121
JL_DLLEXPORT void jl_loader_print_stderr(const char * msg)
2222
{
@@ -31,7 +31,7 @@ void jl_loader_print_stderr3(const char * msg1, const char * msg2, const char *
3131
}
3232

3333
/* Wrapper around dlopen(), with extra relative pathing thrown in*/
34-
static void * load_library(const char * rel_path, const char * src_dir) {
34+
static void * load_library(const char * rel_path, const char * src_dir, int err) {
3535
void * handle = NULL;
3636

3737
// See if a handle is already open to the basename
@@ -65,6 +65,8 @@ static void * load_library(const char * rel_path, const char * src_dir) {
6565
#endif
6666

6767
if (handle == NULL) {
68+
if (!err)
69+
return NULL;
6870
jl_loader_print_stderr3("ERROR: Unable to load dependent library ", path, "\n");
6971
#if defined(_OS_WINDOWS_)
7072
LPWSTR wmsg = TEXT("");
@@ -157,31 +159,75 @@ __attribute__((constructor)) void jl_load_libjulia_internal(void) {
157159
// Pre-load libraries that libjulia-internal needs.
158160
int deps_len = strlen(dep_libs);
159161
char * curr_dep = &dep_libs[0];
162+
163+
// We keep track of "special" libraries names (ones whose name is prefixed with `@`)
164+
// which are libraries that we want to load in some special, custom way, such as
165+
// `libjulia-internal` or `libjulia-codegen`.
166+
int special_idx = 0;
167+
char * special_library_names[2] = {NULL};
160168
while (1) {
161-
// try to find next colon character, if we can't, escape out.
169+
// try to find next colon character; if we can't, break out
162170
char * colon = strchr(curr_dep, ':');
163171
if (colon == NULL)
164172
break;
165173

166-
// Chop the string at the colon, load this library.
174+
// Chop the string at the colon so it's a valid-ending-string
167175
*colon = '\0';
168-
load_library(curr_dep, lib_dir);
176+
177+
// If this library name starts with `@`, don't open it here (but mark it as special)
178+
if (curr_dep[0] == '@') {
179+
if (special_idx > sizeof(special_library_names)/sizeof(char *)) {
180+
jl_loader_print_stderr("ERROR: Too many special library names specified, check LOADER_BUILD_DEP_LIBS and friends!\n");
181+
exit(1);
182+
}
183+
special_library_names[special_idx] = curr_dep + 1;
184+
special_idx += 1;
185+
} else {
186+
load_library(curr_dep, lib_dir, 1);
187+
}
169188

170189
// Skip ahead to next dependency
171190
curr_dep = colon + 1;
172191
}
173192

174-
// Last dependency is `libjulia-internal`, so load that and we're done with `dep_libs`!
175-
libjulia_internal = load_library(curr_dep, lib_dir);
193+
if (special_idx != sizeof(special_library_names)/sizeof(char *)) {
194+
jl_loader_print_stderr("ERROR: Too few special library names specified, check LOADER_BUILD_DEP_LIBS and friends!\n");
195+
exit(1);
196+
}
197+
198+
// Unpack our special library names. This is why ordering of library names matters.
199+
libjulia_internal = load_library(special_library_names[0], lib_dir, 1);
200+
void *libjulia_codegen = load_library(special_library_names[1], lib_dir, 0);
201+
const char * const * codegen_func_names;
202+
if (libjulia_codegen == NULL) {
203+
// if codegen is not available, use fallback implementation in libjulia-internal
204+
libjulia_codegen = libjulia_internal;
205+
codegen_func_names = jl_codegen_fallback_func_names;
206+
}
207+
else {
208+
codegen_func_names = jl_codegen_exported_func_names;
209+
}
176210

177211
// Once we have libjulia-internal loaded, re-export its symbols:
178-
for (unsigned int symbol_idx=0; jl_exported_func_names[symbol_idx] != NULL; ++symbol_idx) {
179-
void *addr = lookup_symbol(libjulia_internal, jl_exported_func_names[symbol_idx]);
212+
for (unsigned int symbol_idx=0; jl_runtime_exported_func_names[symbol_idx] != NULL; ++symbol_idx) {
213+
void *addr = lookup_symbol(libjulia_internal, jl_runtime_exported_func_names[symbol_idx]);
214+
if (addr == NULL) {
215+
jl_loader_print_stderr3("ERROR: Unable to load ", jl_runtime_exported_func_names[symbol_idx], " from libjulia-internal\n");
216+
exit(1);
217+
}
218+
(*jl_runtime_exported_func_addrs[symbol_idx]) = addr;
219+
}
220+
// jl_options must be initialized very early, in case an embedder sets some
221+
// values there before calling jl_init
222+
((void (*)())jl_init_options_addr)();
223+
224+
for (unsigned int symbol_idx=0; codegen_func_names[symbol_idx] != NULL; ++symbol_idx) {
225+
void *addr = lookup_symbol(libjulia_codegen, codegen_func_names[symbol_idx]);
180226
if (addr == NULL) {
181-
jl_loader_print_stderr3("ERROR: Unable to load ", jl_exported_func_names[symbol_idx], " from libjulia-internal\n");
227+
jl_loader_print_stderr3("ERROR: Unable to load ", codegen_func_names[symbol_idx], " from libjulia-codegen\n");
182228
exit(1);
183229
}
184-
(*jl_exported_func_addrs[symbol_idx]) = addr;
230+
(*jl_codegen_exported_func_addrs[symbol_idx]) = addr;
185231
}
186232

187233
// jl_options must be initialized very early, in case an embedder sets some

cli/trampolines/trampolines_aarch64.S

+3-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ CNAME(name)##: SEP \
1313
br x16 SEP \
1414
.cfi_endproc SEP \
1515

16-
JL_EXPORTED_FUNCS(XX)
16+
JL_RUNTIME_EXPORTED_FUNCS(XX)
1717
#ifdef _OS_WINDOWS_
18-
JL_EXPORTED_FUNCS_WIN(XX)
18+
JL_RUNTIME_EXPORTED_FUNCS_WIN(XX)
1919
#endif
20+
JL_CODEGEN_EXPORTED_FUNCS(XX)
2021
#undef XX

cli/trampolines/trampolines_arm.S

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ CONCAT(.L,CNAMEADDR(name))##: ; \
1616
.word CNAMEADDR(name)##-(CONCAT(.L,CNAME(name)) + 8); \
1717
.cfi_endproc; \
1818

19-
JL_EXPORTED_FUNCS(XX)
19+
JL_RUNTIME_EXPORTED_FUNCS(XX)
2020
#ifdef _OS_WINDOWS_
21-
JL_EXPORTED_FUNCS_WIN(XX)
21+
JL_RUNTIME_EXPORTED_FUNCS_WIN(XX)
2222
#endif
23+
JL_CODEGEN_EXPORTED_FUNCS(XX)
2324
#undef XX

cli/trampolines/trampolines_i686.S

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ CNAME(name)##:; \
1414
.cfi_endproc; \
1515
EXPORT(name); \
1616

17-
JL_EXPORTED_FUNCS(XX)
17+
JL_RUNTIME_EXPORTED_FUNCS(XX)
1818
#ifdef _OS_WINDOWS_
19-
JL_EXPORTED_FUNCS_WIN(XX)
19+
JL_RUNTIME_EXPORTED_FUNCS_WIN(XX)
2020
#endif
21+
JL_CODEGEN_EXPORTED_FUNCS(XX)
2122
#undef XX

cli/trampolines/trampolines_powerpc64le.S

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ CNAME(name)##: ; \
2424
.cfi_endproc; \
2525
.size CNAME(name)##,.-CNAME(name)##; \
2626

27-
JL_EXPORTED_FUNCS(XX)
27+
JL_RUNTIME_EXPORTED_FUNCS(XX)
28+
JL_CODEGEN_EXPORTED_FUNCS(XX)
2829
#undef XX

cli/trampolines/trampolines_x86_64.S

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ SEH_END(); \
1818
.cfi_endproc; \
1919
EXPORT(name); \
2020

21-
JL_EXPORTED_FUNCS(XX)
21+
JL_RUNTIME_EXPORTED_FUNCS(XX)
2222
#ifdef _OS_WINDOWS_
23-
JL_EXPORTED_FUNCS_WIN(XX)
23+
JL_RUNTIME_EXPORTED_FUNCS_WIN(XX)
2424
#endif
25+
JL_CODEGEN_EXPORTED_FUNCS(XX)
2526
#undef XX

0 commit comments

Comments
 (0)