Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Have a try at upgrading to LLVM 15 #11

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Have a try at upgrading to LLVM 15 #11

wants to merge 2 commits into from

Conversation

kit-ty-kate
Copy link
Owner

Trying alan-j-hu/llvm-dune#9 but it still segfaults.

@alan-j-hu What should i do? Is Llvm.set_opaque_pointers meant to be used another way?

@kit-ty-kate
Copy link
Owner Author

Here is the valgrind backtrace i got:

PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
==72926== 
==72926== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==72926==  Access not within mapped region at address 0xEADD2
==72926==    at 0x5963A90: LLVMBuildGEP (in /usr/lib/libLLVM-15.so)
==72926==    by 0x70189B: llvm_build_gep (llvm_ocaml.c:2584)
==72926==    by 0x7348FF: caml_c_call (in /tmp/labrys/_build/default/src/main.exe)
==72926==  If you believe this happened as a result of a stack
==72926==  overflow in your program's main thread (unlikely but
==72926==  possible), you can try to increase the size of the
==72926==  main thread stack using the --main-stacksize= flag.
==72926==  The main thread stack size used in this run was 8388608.
==72926== 
==72926== HEAP SUMMARY:
==72926==     in use at exit: 3,058,919 bytes in 2,856 blocks
==72926==   total heap usage: 3,448 allocs, 592 frees, 3,949,060 bytes allocated
==72926== 
==72926== LEAK SUMMARY:
==72926==    definitely lost: 1,829 bytes in 2 blocks
==72926==    indirectly lost: 0 bytes in 0 blocks
==72926==      possibly lost: 6,764 bytes in 75 blocks
==72926==    still reachable: 3,050,326 bytes in 2,779 blocks
==72926==         suppressed: 0 bytes in 0 blocks
==72926== Rerun with --leak-check=full to see details of leaked memory
==72926== 
==72926== For lists of detected and suppressed errors, rerun with: -s
==72926== ERROR SUMMARY: 2021 errors from 1000 contexts (suppressed: 0 from 0)
72926 Segmentation fault      (core dumped) valgrind labrys build-program Basic.sfw

@alan-j-hu
Copy link

alan-j-hu commented Jul 31, 2023

Does your code work in LLVM 14? I'm getting curious segfaults from LLVMBuildGEP when I tried a test program, but I don't know if I'm doing something stupid.

#include <llvm-c/Core.h>
#include <stddef.h>

int main()
{
  LLVMContextRef ctx = LLVMGetGlobalContext();
  // LLVMContextSetOpaquePointers(ctx, 0);
  LLVMModuleRef m = LLVMModuleCreateWithNameInContext("mod", ctx);
  LLVMTypeRef argtys[] = {
    LLVMInt32Type(),
    LLVMPointerType(LLVMPointerType(LLVMInt8Type(), 0), 0)
  };
  LLVMTypeRef fty = LLVMFunctionType(LLVMInt32Type(), argtys, 2, 0);
  LLVMValueRef main = LLVMAddFunction(m, "main", fty);
  LLVMBasicBlockRef bb = LLVMAppendBasicBlockInContext(ctx, main, "entry");
  LLVMBuilderRef b = LLVMCreateBuilderInContext(ctx);
  LLVMPositionBuilderAtEnd(b, bb);
  LLVMValueRef indices[] = {
    LLVMConstInt(LLVMInt32Type(), 0, 0),
    LLVMConstInt(LLVMInt32Type(), 0, 0)
  };
  LLVMBuildGEP(b, LLVMGetParam(main, 1), indices, 2, "gep");
  LLVMValueRef args[] = {
    LLVMGetParam(main, 0),
    LLVMGetParam(main, 1)
  };
  LLVMValueRef call = LLVMBuildCall(b, main, args, 2, "rec");
  LLVMBuildRet(b, call);
  LLVMDumpModule(m);
  LLVMDisposeModule(m);
  return 0;
}

compiled with cc test.c `llvm-config-14 --cflags --ldflags --libs core`.

@kit-ty-kate
Copy link
Owner Author

kit-ty-kate commented Jul 31, 2023

Does your code work in LLVM 14? I'm getting curious segfaults from LLVMBuildGEP when I tried a test program using LLVMBuildGEP.

No, but for different reason: see #10 (I'm guessing it should work if we tried to backport your nnp patch to LLVM 14 but we'll never know)

@alan-j-hu
Copy link

I read the getelementpointer documentation more closely, and I think I probably used it wrong. What I was doing, indexing twice into an i8** via GEP, was probably not correct. For what it's worth, the following:

#include <llvm-c/Core.h>
#include <stddef.h>

int main()
{
  LLVMContextRef ctx = LLVMGetGlobalContext();
  LLVMContextSetOpaquePointers(ctx, 0);
  LLVMModuleRef m = LLVMModuleCreateWithNameInContext("mod", ctx);
  LLVMTypeRef argtys[] = {
    LLVMInt32Type(),
    LLVMPointerType(LLVMPointerType(LLVMInt8Type(), 0), 0)
  };
  LLVMTypeRef fty = LLVMFunctionType(LLVMInt32Type(), argtys, 2, 0);
  LLVMValueRef main = LLVMAddFunction(m, "main", fty);
  LLVMBasicBlockRef bb = LLVMAppendBasicBlockInContext(ctx, main, "entry");
  LLVMBuilderRef b = LLVMCreateBuilderInContext(ctx);
  LLVMPositionBuilderAtEnd(b, bb);
  LLVMValueRef indices[] = {
    LLVMConstInt(LLVMInt32Type(), 0, 0)
  };
  LLVMBuildGEP(b, LLVMGetParam(main, 1), indices, 1, "gep");
  LLVMValueRef args[] = {
    LLVMGetParam(main, 0),
    LLVMGetParam(main, 1)
  };
  LLVMValueRef call = LLVMBuildCall(b, main, args, 2, "rec");
  LLVMBuildRet(b, call);
  LLVMDumpModule(m);
  LLVMDisposeModule(m);
  return 0;
}

compiled with cc test.c `llvm-config-15 --cflags --ldflags --libs core` works fine, while taking out the line disabling opaque pointers mode causes the program to segfault.

@kit-ty-kate
Copy link
Owner Author

Unless some expectations around GEP changed between LLVM 12 (where it definitely worked) and 15, i don't think this is the same kind of error

@alan-j-hu
Copy link

Yeah, I can see your code is different than the likely incorrect thing I tried to do in my first test program. From what I can tell, you have a global called gc_heap of type i8* and a global called gc_heap_cursor of type i32, and you load both and then use GEP to calculate the result of offsetting gc_heap_cursor from gc_heap. Is that right?

@kit-ty-kate
Copy link
Owner Author

if i remember correctly, yes

@alan-j-hu
Copy link

#include <llvm-c/Core.h>
#include <stddef.h>

int main()
{
  LLVMContextRef ctx = LLVMGetGlobalContext();
  LLVMContextSetOpaquePointers(ctx, 0);
  LLVMModuleRef m = LLVMModuleCreateWithNameInContext("mod", ctx);

  LLVMValueRef gcglob =
    LLVMAddGlobal(m, LLVMPointerType(LLVMInt8Type(), 0), "gc");
  LLVMValueRef offglob =
    LLVMAddGlobal(m, LLVMInt32Type(), "offset");

  LLVMTypeRef fty = LLVMFunctionType(LLVMInt32Type(), NULL, 0, 0);
  LLVMValueRef main = LLVMAddFunction(m, "main", fty);
  LLVMBasicBlockRef bb = LLVMAppendBasicBlockInContext(ctx, main, "entry");
  LLVMBuilderRef b = LLVMCreateBuilderInContext(ctx);
  LLVMPositionBuilderAtEnd(b, bb);
  LLVMValueRef gc = LLVMBuildLoad(b, gcglob, "");
  LLVMValueRef off = LLVMBuildLoad(b, offglob, "");
  LLVMValueRef indices[] = { off };
  LLVMBuildGEP(b, gc, indices, 1, "gep");
  LLVMBuildRet(b, LLVMConstInt(LLVMInt32Type(), 0, 0));
  LLVMDumpModule(m);
  LLVMDisposeModule(m);
  return 0;
}

Does this test program (which works) represent what your code does?

What are the steps you took to install my forked LLVM to opam and build and test this project? I want to investigate what is happening.

@kit-ty-kate
Copy link
Owner Author

Does this test program (which works) represent what your code does?

I'm not sure but here is a close to minimal reproduction case using the OCaml binding:

$ cat dune
(env (_ (flags (:standard -w -3))))

(executable
 (name test)
 (libraries llvm))
$ cat dune-project
(lang dune 2.0)

the content of test.ml:

let c = Llvm.global_context ()
let () = Llvm.set_opaque_pointers c false
let m = Llvm.create_module c "_main_"

let i8 = Llvm.i8_type c
let i32 = Llvm.i32_type c
let star = Llvm.pointer_type i8

let gc_heap = Llvm.define_global "GC_heap" (Llvm.const_null star) m
let gc_heap_cursor = Llvm.define_global "GC_heap_cursor" (Llvm.const_int i32 0) m

let fill_gc_malloc builder =
  let current_heap_cursor = Llvm.build_load gc_heap_cursor "" builder in
  let (res, builder) =
    let func = Llvm.block_parent (Llvm.insertion_block builder) in
    let block = Llvm.append_block c "" func in
    let builder = Llvm.builder_at_end c block in
    let current_heap = Llvm.build_load gc_heap "" builder in
    let _ = Llvm.build_gep current_heap [|current_heap_cursor|] "" builder in
    assert false (* BOOM *)
  in
  Llvm.build_ret res builder

let () =
  let f = Llvm.define_function "GC_malloc" (Llvm.function_type star [|i32|]) m in
  let _ = fill_gc_malloc (Llvm.builder_at_end c (Llvm.entry_block f)) in
  ()

Just do dune exec -- ./test.exe and you'll see the segfault.

What are the steps you took to install my forked LLVM to opam and build and test this project?

Simply by doing the installation by hand (see opam file), from the source directory:

$ ./setup.sh llvm-config-15
$ dune build --release
$ ./install.sh ~/.opam/5.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants