From 886116fb90caf3649b1a0203156f231a7d60b82d Mon Sep 17 00:00:00 2001 From: gbaraldi Date: Tue, 11 Feb 2025 18:28:05 -0300 Subject: [PATCH 1/4] Use ptrdiff_t sized offsets for gvars_offsets to allow large sysimages --- src/aotcompile.cpp | 13 +++++++------ src/processor.cpp | 2 +- src/processor.h | 4 ++-- src/staticdata.c | 2 +- test/llvmpasses/multiversioning-clone-only.ll | 4 ++-- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index d91da9c64cda9..934541630c4d7 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -4,6 +4,8 @@ #include "platform.h" // target support +#include "llvm/IR/Constants.h" +#include "llvm/Support/Debug.h" #include #include "llvm/Support/CodeGen.h" #include @@ -199,29 +201,28 @@ static inline SmallVector consume_gv(Module &M, const char *name, bool al return res; } -static Constant *get_ptrdiff32(Type *T_size, Constant *ptr, Constant *base) +static Constant *get_ptrdiff(Type *T_size, Constant *ptr, Constant *base) { if (ptr->getType()->isPointerTy()) ptr = ConstantExpr::getPtrToInt(ptr, T_size); auto ptrdiff = ConstantExpr::getSub(ptr, base); - return T_size->getPrimitiveSizeInBits() > 32 ? ConstantExpr::getTrunc(ptrdiff, Type::getInt32Ty(ptr->getContext())) : ptrdiff; + return ptrdiff; } static Constant *emit_offset_table(Module &M, Type *T_size, ArrayRef vars, StringRef name, StringRef suffix) { - auto T_int32 = Type::getInt32Ty(M.getContext()); uint32_t nvars = vars.size(); - ArrayType *vars_type = ArrayType::get(T_int32, nvars + 1); + ArrayType *vars_type = ArrayType::get(T_size, nvars + 1); auto gv = new GlobalVariable(M, vars_type, true, GlobalVariable::ExternalLinkage, nullptr, name + "_offsets" + suffix); auto vbase = ConstantExpr::getPtrToInt(gv, T_size); SmallVector offsets(nvars + 1); - offsets[0] = ConstantInt::get(T_int32, nvars); + offsets[0] = ConstantInt::get(T_size, nvars); for (uint32_t i = 0; i < nvars; i++) - offsets[i + 1] = get_ptrdiff32(T_size, vars[i], vbase); + offsets[i + 1] = get_ptrdiff(T_size, vars[i], vbase); gv->setInitializer(ConstantArray::get(vars_type, offsets)); gv->setVisibility(GlobalValue::HiddenVisibility); gv->setDSOLocal(true); diff --git a/src/processor.cpp b/src/processor.cpp index 3edebcc2f3ae6..aebc04fd96d90 100644 --- a/src/processor.cpp +++ b/src/processor.cpp @@ -772,7 +772,7 @@ static inline jl_image_t parse_sysimg(void *hdl, F &&callback) } if (!gvars.empty()) { - auto offsets = (int32_t*)malloc(sizeof(int32_t) * gvars.size()); + auto offsets = (ptrdiff_t*)malloc(sizeof(ptrdiff_t) * gvars.size()); res.gvars_base = (const char*)pointers->header; for (size_t i = 0; i < gvars.size(); i++) { assert(gvars[i] && "Missing global variable pointer!"); diff --git a/src/processor.h b/src/processor.h index 82a1121aaf7c4..e71551b5bada2 100644 --- a/src/processor.h +++ b/src/processor.h @@ -85,7 +85,7 @@ typedef struct _jl_image_fptrs_t { typedef struct { uint64_t base; const char *gvars_base; - const int32_t *gvars_offsets; + const ptrdiff_t *gvars_offsets; uint32_t ngvars; jl_image_fptrs_t fptrs; void **jl_small_typeof; @@ -126,7 +126,7 @@ typedef struct { // Similar to fvar_offsets, but for gvars // This is also the base data pointer // (all data pointers in this shard are stored as offsets to this address) - const int32_t *gvar_offsets; + const ptrdiff_t *gvar_offsets; // This is the mapping of shard global variable index -> global global variable index // Similar to fvar_idxs, but for gvars const uint32_t *gvar_idxs; diff --git a/src/staticdata.c b/src/staticdata.c index 6cb157ad299fc..ca2cfcaf44bfc 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -635,7 +635,7 @@ typedef struct { static void *jl_sysimg_handle = NULL; static jl_image_t sysimage; -static inline uintptr_t *sysimg_gvars(const char *base, const int32_t *offsets, size_t idx) +static inline uintptr_t *sysimg_gvars(const char *base, const ptrdiff_t *offsets, size_t idx) { return (uintptr_t*)(base + offsets[idx]); } diff --git a/test/llvmpasses/multiversioning-clone-only.ll b/test/llvmpasses/multiversioning-clone-only.ll index 00f0db0aa1e91..9b74a2c4aaf78 100644 --- a/test/llvmpasses/multiversioning-clone-only.ll +++ b/test/llvmpasses/multiversioning-clone-only.ll @@ -3,7 +3,7 @@ ; RUN: opt --load-pass-plugin=libjulia-codegen%shlibext -passes='JuliaMultiVersioning' -S %s | FileCheck %s --allow-unused-prefixes=false --check-prefixes=CHECK,OPAQUE ; CHECK: @jl_gvar_base = hidden constant i64 0 -; CHECK: @jl_gvar_offsets = hidden constant [0 x i32] zeroinitializer +; CHECK: @jl_gvar_offsets = hidden constant [0 x i64] zeroinitializer ; CHECK: @jl_fvar_idxs = hidden constant [1 x i32] zeroinitializer ; CHECK: @jl_gvar_idxs = hidden constant [0 x i32] zeroinitializer ; OPAQUE: @subtarget_cloned_gv = hidden global ptr null @@ -18,7 +18,7 @@ @jl_fvars = global [1 x i64*] [i64* bitcast (i32 (i32)* @subtarget_cloned to i64*)], align 8 @jl_gvar_base = hidden constant i64 zeroinitializer, align 8 -@jl_gvar_offsets = hidden constant [0 x i32] zeroinitializer, align 8 +@jl_gvar_offsets = hidden constant [0 x i64] zeroinitializer, align 8 @jl_fvar_idxs = hidden constant [1 x i32] [i32 0], align 8 @jl_gvar_idxs = hidden constant [0 x i32] zeroinitializer, align 8 @subtarget_cloned_gv = hidden global i64* bitcast (i32 (i32)* @subtarget_cloned to i64*), align 8 From 9670d8e4233f878a1ad6058017a3d1bc0e122387 Mon Sep 17 00:00:00 2001 From: Gabriel Baraldi Date: Wed, 12 Feb 2025 18:37:46 -0300 Subject: [PATCH 2/4] Add julia level test for large sysimages --- test/compileall.jl | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/test/compileall.jl b/test/compileall.jl index beec0d6df49ab..767b32a8845f0 100644 --- a/test/compileall.jl +++ b/test/compileall.jl @@ -2,10 +2,22 @@ # We make it a separate test target here, so that it can run in parallel # with the rest of the tests. -mktempdir() do dir - @test success(pipeline(`$(Base.julia_cmd()) --compile=all --strip-ir --output-o $(dir)/sys.o.a -e 'exit()'`, stderr=stderr)) skip=(Sys.WORD_SIZE == 32) - if isfile(joinpath(dir, "sys.o.a")) - Base.Linking.link_image(joinpath(dir, "sys.o.a"), joinpath(dir, "sys.so")) - @test success(`$(Base.julia_cmd()) -J $(dir)/sys.so -e 'Base.scrub_repl_backtrace(nothing); exit()'`) + + +if !Sys.iswindows() #Windows doesn't support large images + mktempdir() do dir + @test success(pipeline(`$(Base.julia_cmd()) --compile=all --strip-ir --output-o $(dir)/sys.o.a -e 'const ballast = Memory{UInt8}(undef, 1 << 31); exit()'`, stderr=stderr)) skip=(Sys.WORD_SIZE == 32) + if isfile(joinpath(dir, "sys.o.a")) + Base.Linking.link_image(joinpath(dir, "sys.o.a"), joinpath(dir, "sys.so")) + @test success(`$(Base.julia_cmd()) -J $(dir)/sys.so -e 'Base.scrub_repl_backtrace(nothing); exit()'`) + end + end +else + mktempdir() do dir + @test success(pipeline(`$(Base.julia_cmd()) --compile=all --strip-ir --output-o $(dir)/sys.o.a -e 'exit()'`, stderr=stderr)) skip=(Sys.WORD_SIZE == 32) + if isfile(joinpath(dir, "sys.o.a")) + Base.Linking.link_image(joinpath(dir, "sys.o.a"), joinpath(dir, "sys.so")) + @test success(`$(Base.julia_cmd()) -J $(dir)/sys.so -e 'Base.scrub_repl_backtrace(nothing); exit()'`) + end end end From 4170a4a32f6a34f7a7491e9dc630742b2abb70b4 Mon Sep 17 00:00:00 2001 From: Gabriel Baraldi Date: Wed, 19 Feb 2025 13:19:00 -0300 Subject: [PATCH 3/4] Change logic slightly --- test/compileall.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/compileall.jl b/test/compileall.jl index 767b32a8845f0..3e295f9537f51 100644 --- a/test/compileall.jl +++ b/test/compileall.jl @@ -4,9 +4,9 @@ -if !Sys.iswindows() #Windows doesn't support large images +if !Sys.iswindows() && !(Sys.WORD_SIZE == 32) #Windows doesn't support large images mktempdir() do dir - @test success(pipeline(`$(Base.julia_cmd()) --compile=all --strip-ir --output-o $(dir)/sys.o.a -e 'const ballast = Memory{UInt8}(undef, 1 << 31); exit()'`, stderr=stderr)) skip=(Sys.WORD_SIZE == 32) + @test success(pipeline(`$(Base.julia_cmd()) --compile=all --strip-ir --output-o $(dir)/sys.o.a -e 'const ballast = Memory{UInt8}(undef, 1 << 31); exit()'`, stderr=stderr)) if isfile(joinpath(dir, "sys.o.a")) Base.Linking.link_image(joinpath(dir, "sys.o.a"), joinpath(dir, "sys.so")) @test success(`$(Base.julia_cmd()) -J $(dir)/sys.so -e 'Base.scrub_repl_backtrace(nothing); exit()'`) From 8a079963a2ee1f37b844ff18dc660b91a742ddb1 Mon Sep 17 00:00:00 2001 From: Gabriel Baraldi Date: Fri, 21 Feb 2025 19:51:11 -0300 Subject: [PATCH 4/4] Set medium code model on darwin too --- src/aotcompile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index 934541630c4d7..fe340d849d8c0 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -1992,7 +1992,7 @@ void jl_dump_native_impl(void *native_code, CodeModel::Model CMModel = CodeModel::Small; if (TheTriple.isPPC() || TheTriple.isRISCV() || - (TheTriple.isX86() && TheTriple.isArch64Bit() && TheTriple.isOSLinux())) { + (TheTriple.isX86() && TheTriple.isArch64Bit() && (TheTriple.isOSLinux() || TheTriple.isOSDarwin()))) { // On PPC the small model is limited to 16bit offsets. For very large images the small code model CMModel = CodeModel::Medium; // isn't good enough on x86 so use Medium, it has no cost because only the image goes in .ldata }