Skip to content

Commit

Permalink
fix alignment of emit_unbox_store copy
Browse files Browse the repository at this point in the history
The dest alignment might be determined to be greater than the source.
For example, observed with:

    code_llvm(dump_module=true, optimize=false, (Int,)) do x
        Pair(ntuple(i -> 0x00, 8), x)
    end

Where the alignment of the first field of the Pair is at least 4, but
the alignment of the ntuple data is 1.
  • Loading branch information
vtjnash committed Dec 12, 2023
1 parent 9374e49 commit 3b68a67
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 3 deletions.
7 changes: 6 additions & 1 deletion doc/src/devdocs/debuggingtips.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,16 @@ useful.

## Useful Julia functions for Inspecting those variables

* `jl_gdblookup($rip)` :: For looking up the current function and line. (use `$eip` on i686 platforms)
* `jl_print_task_backtraces(0)` :: Similar to gdb's `thread apply all bt` or lldb's `thread backtrace
all`. Runs all threads while printing backtraces for all existing tasks.
* `jl_gdblookup($pc)` :: For looking up the current function and line.
* `jl_gdblookupinfo($pc)` :: For looking up the current method instance object.
* `jl_gdbdumpcode(mi)` :: For dumping all of `code_typed/code_llvm/code_asm` when the REPL is not working right.
* `jlbacktrace()` :: For dumping the current Julia backtrace stack to stderr. Only usable after
`record_backtrace()` has been called.
* `jl_dump_llvm_value(Value*)` :: For invoking `Value->dump()` in gdb, where it doesn't work natively.
For example, `f->linfo->functionObject`, `f->linfo->specFunctionObject`, and `to_function(f->linfo)`.
* `jl_dump_llvm_module(Module*)` :: For invoking `Module->dump()` in gdb, where it doesn't work natively.
* `Type->dump()` :: only works in lldb. Note: add something like `;1` to prevent lldb from printing
its prompt over the output
* `jl_eval_string("expr")` :: for invoking side-effects to modify the current state or to lookup
Expand Down
52 changes: 52 additions & 0 deletions src/aotcompile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1820,6 +1820,58 @@ void addTargetPasses(legacy::PassManagerBase *PM, const Triple &triple, TargetIR
PM->add(createTargetTransformInfoWrapperPass(std::move(analysis)));
}

// sometimes in GDB you want to find out what code was created from a mi
extern "C" JL_DLLEXPORT_CODEGEN jl_code_info_t *jl_gdbdumpcode(jl_method_instance_t *mi)
{
jl_llvmf_dump_t llvmf_dump;
size_t world = jl_current_task->world_age;
JL_STREAM *stream = (JL_STREAM*)STDERR_FILENO;

jl_printf(stream, "---- dumping IR for ----\n");
jl_static_show(stream, (jl_value_t*)mi);
jl_printf(stream, "\n----\n");

jl_printf(stream, "\n---- unoptimized IR ----");
jl_get_llvmf_defn(&llvmf_dump, mi, world, 0, false, jl_default_cgparams);
if (llvmf_dump.F) {
jl_value_t *ir = jl_dump_function_ir(&llvmf_dump, 0, 1, "source");
jl_static_show(stream, ir);
}
jl_printf(stream, "----\n");

jl_printf(stream, "\n---- optimized IR ----");
jl_get_llvmf_defn(&llvmf_dump, mi, world, 0, true, jl_default_cgparams);
if (llvmf_dump.F) {
jl_value_t *ir = jl_dump_function_ir(&llvmf_dump, 0, 1, "source");
jl_static_show(stream, ir);
}
jl_printf(stream, "----\n");

jl_printf(stream, "\n---- assembly ----");
jl_get_llvmf_defn(&llvmf_dump, mi, world, 0, true, jl_default_cgparams);
if (llvmf_dump.F) {
jl_value_t *ir = jl_dump_function_asm(&llvmf_dump, 0, "", "source", 0, true);
jl_static_show(stream, ir);
}
jl_printf(stream, "----\n");

jl_code_info_t *src = NULL;
jl_value_t *ci = jl_default_cgparams.lookup(mi, world, world);
if (ci != jl_nothing) {
jl_code_instance_t *codeinst = (jl_code_instance_t*)ci;
src = (jl_code_info_t*)jl_atomic_load_relaxed(&codeinst->inferred);
if ((jl_value_t*)src != jl_nothing && !jl_is_code_info(src) && jl_is_method(mi->def.method)) {
JL_GC_PUSH1(&codeinst);
src = jl_uncompress_ir(mi->def.method, codeinst, (jl_value_t*)src);
JL_GC_POP();
}
}
if (!src || (jl_value_t*)src == jl_nothing) {
src = jl_type_infer(mi, world, 0);
}
return src;
}

// --- native code info, and dump function to IR and ASM ---
// Get pointer to llvm::Function instance, compiling if necessary
// for use in reflection from Julia.
Expand Down
3 changes: 2 additions & 1 deletion src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2911,7 +2911,8 @@ static void init_bits_cgval(jl_codectx_t &ctx, Value *newv, const jl_cgval_t& v,
{
// newv should already be tagged
if (v.ispointer()) {
emit_memcpy(ctx, newv, jl_aliasinfo_t::fromTBAA(ctx, tbaa), v, jl_datatype_size(v.typ), sizeof(void*), julia_alignment(v.typ));
unsigned align = std::max(julia_alignment(v.typ), (unsigned)sizeof(void*));
emit_memcpy(ctx, newv, jl_aliasinfo_t::fromTBAA(ctx, tbaa), v, jl_datatype_size(v.typ), align, julia_alignment(v.typ));
}
else {
init_bits_value(ctx, newv, v.V, tbaa);
Expand Down
2 changes: 1 addition & 1 deletion src/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ static void emit_unbox_store(jl_codectx_t &ctx, const jl_cgval_t &x, Value *dest
}

Value *src = data_pointer(ctx, x);
emit_memcpy(ctx, dest, jl_aliasinfo_t::fromTBAA(ctx, tbaa_dest), src, jl_aliasinfo_t::fromTBAA(ctx, x.tbaa), jl_datatype_size(x.typ), alignment, alignment, isVolatile);
emit_memcpy(ctx, dest, jl_aliasinfo_t::fromTBAA(ctx, tbaa_dest), src, jl_aliasinfo_t::fromTBAA(ctx, x.tbaa), jl_datatype_size(x.typ), alignment, julia_alignment(x.typ), isVolatile);
}

static jl_datatype_t *staticeval_bitstype(const jl_cgval_t &targ)
Expand Down

0 comments on commit 3b68a67

Please sign in to comment.