[LLVMdev] Problem linking and JITing code through C++-API

Reed Kotler rkotler at mips.com
Tue Sep 2 15:33:23 PDT 2014


Have you tried running this under gdb and looking at where the 
segmentation fault occurs?


On 09/01/2014 04:41 PM, Andy Jost wrote:
> I have a frontend that generates some LLVM bitcode that needs to be
> linked with other bitcode (its runtime library), which I generate from
> C++ source using Clang.
>
> If I write the output of my program to disk, link it with llvm-link, and
> then run it with lli, everything works perfectly.  But if I try to
> perform the linking and running steps in my main program, I get this
> error during llvm::ExecutionEngine::getPointerToFunction:
>
> Stack dump:
>
> 0.      Running pass 'X86 Machine Code Emitter' on function
> '@.step.myappend'
>
> 1.      Running pass 'X86 Machine Code Emitter' on function
> '@.step.myappend'
>
> Segmentation fault (core dumped)
>
> There are no other messages.  Any idea what I’m doing wrong?  I’ll copy
> the source of my main C++ file and the bitcode for .step.myappend
> below.  I can send the full bitcode file, too, if someone asks for it,
> but it is around 800 lines.
>
> ####################
>
> #include <fstream>
>
> #include <iostream>
>
> #include "llvm/Bitcode/ReaderWriter.h"
>
> #include "llvm/ExecutionEngine/JIT.h"
>
> #include "llvm/IR/DataLayout.h"
>
> #include "llvm/Linker.h"
>
> #include "llvm/PassManager.h"
>
> #include "llvm/Support/MemoryBuffer.h"
>
> #include "llvm/Support/raw_ostream.h"
>
> #include "llvm/Support/system_error.h"
>
> #include "llvm/Support/TargetSelect.h"
>
> #include "llvm/Transforms/IPO.h"
>
> #include "llvm/Transforms/Scalar.h"
>
> #include "sprite/compiler.hpp"
>
> #include "sprite/config.hpp"
>
> #include "sprite/curryinput.hpp"
>
> #include "sprite/icurry_parser.hpp"
>
> namespace
>
> {
>
>    std::string dirname(std::string const & path)
>
>    {
>
>      size_t const pos = path.find_last_of("/");
>
>      return path.substr(0, pos == std::string::npos ? 0 : pos);
>
>    }
>
>    std::string basename(std::string const & path)
>
>    {
>
>      size_t const pos = path.find_last_of("/");
>
>      return path.substr(pos == std::string::npos ? 0 : pos + 1);
>
>    }
>
>    std::string remove_extension(std::string const & path)
>
>    {
>
>      size_t const pos = path.find_last_of(".");
>
>      return pos == std::string::npos ? path : path.substr(0, pos);
>
>    }
>
>    std::string joinpath(std::string const & dirname, std::string const &
> path)
>
>    {
>
>      if(!path.empty() && path.front() == '/')
>
>        return path;
>
>      if(dirname.empty())
>
>        return path;
>
>      return dirname.back() == '/' ? dirname + path : dirname + "/" + path;
>
>    }
>
> }
>
> int main(int argc, char const *argv[])
>
> {
>
>    if(argc != 2)
>
>    {
>
>     std::cerr << "Usage: " << argv[0] << " <file.curry>" << std::endl;
>
>      return 1;
>
>    }
>
>    std::string const curry2read =
>
>        std::string(SPRITE_LIBINSTALL) + "/cmc/translator/bin/curry2read";
>
>    std::string const curryfile(argv[1]);
>
>    std::string const readablefile = joinpath(
>
>        dirname(curryfile)
>
>      , ".curry/" + remove_extension(basename(curryfile)) + ".read"
>
>      );
>
>    // Generate the readable Curry file.
>
>    int ok = std::system((curry2read + " -q " + curryfile).c_str());
>
>    if(ok != 0) return 1;
>
>    std::ifstream input(readablefile);
>
>    if(!input)
>
>    {
>
>      std::cerr << "Could not open \"" << readablefile << "\"" << std::endl;
>
>      return 1;
>
>    }
>
>    // Parse the input program.
>
>    sprite::curry::Library lib;
>
>    input >> lib;
>
>    std::string topmodule = lib.modules.front().name;
>
>    // sprite::compiler::prettyprint(lib);
>
>    // Compile the program.
>
>    sprite::compiler::LibrarySTab stab;
>
>    sprite::compiler::compile(lib, stab);
>
>    // Declare the main function.
>
>    namespace tgt = sprite::backend;
>
>    auto & module_stab = stab.modules.at(topmodule);
>
>    auto & compiler = *module_stab.compiler;
>
>    tgt::scope _ = module_stab.module_ir;
>
>    tgt::extern_(
>
>        tgt::types::int_(32)(), "main", {}
>
>      , [&]{
>
>          // Construct the root expression (just the "main" symbol).
>
>          tgt::value root_p = compiler.node_alloc();
>
>          sprite::curry::Qname const main_{topmodule, "main"};
>
>          root_p = construct(compiler, root_p, {main_, {}});
>
>          // Evaluate and then print the root expression.
>
>          compiler.rt.normalize(root_p);
>
>          compiler.rt.printexpr(root_p, "\n");
>
>          tgt::return_(0);
>
>        }
>
>      );
>
>    // module_stab.module_ir->dump();
>
>    // Load the runtime library.
>
>    llvm::OwningPtr<llvm::MemoryBuffer> buffer;
>
>    llvm::error_code err = llvm::MemoryBuffer::getFile(
>
>        SPRITE_LIBINSTALL "/sprite-rt.bc", buffer
>
>      );
>
>    if(err)
>
>    {
>
>      std::cerr << err.message() << std::endl;
>
>      return EXIT_FAILURE;
>
>    }
>
>    // Make the runtime library into a module.
>
>    std::string errmsg;
>
>    llvm::Module *rtlib = llvm::ParseBitcodeFile(
>
>        buffer.get(), module_stab.module_ir.context(), &errmsg
>
>      );
>
>    if(!rtlib)
>
>    {
>
>      std::cerr << errmsg << std::endl;
>
>      return EXIT_FAILURE;
>
>    }
>
>    // Link the compiled program code into the runtime module.
>
>    bool failed = llvm::Linker::LinkModules(
>
>        rtlib, module_stab.module_ir.ptr(), llvm::Linker::PreserveSource,
> &errmsg
>
>      );
>
>    if(failed)
>
>    {
>
>      std::cerr << errmsg << std::endl;
>
>      return EXIT_FAILURE;
>
>    }
>
>    std::cout << "Linking done..." << std::endl;
>
>    rtlib->dump();
>
>    // Run optimization passes.
>
>    // std::vector<const char *> exportList;
>
>    // llvm::PassManager Passes;
>
>    // Passes.add(new llvm::DataLayout(rtlib));
>
>    // Passes.add(llvm::createDemoteRegisterToMemoryPass());
>
>    // Passes.add(llvm::createInternalizePass(exportList));
>
>    // Passes.add(llvm::createScalarReplAggregatesPass());
>
>    // Passes.add(llvm::createInstructionCombiningPass());
>
>    // Passes.add(llvm::createGlobalOptimizerPass());
>
>    // Passes.add(llvm::createFunctionInliningPass());
>
>    // Passes.run(*rtlib);
>
>    // Create the JIT
>
>    llvm::InitializeNativeTarget();
>
>    llvm::ExecutionEngine * jit = llvm::EngineBuilder(rtlib)
>
>        .setErrorStr(&errmsg)
>
>        .setEngineKind(llvm::EngineKind::JIT)
>
>        .create();
>
>    if(!jit)
>
>    {
>
>      std::cerr << "Failed to create JIT compiler: " << errmsg << std::endl;
>
>      return EXIT_FAILURE;
>
>    }
>
>    // Execute the program.
>
>    std::cout << "Begin Execution..." << std::endl;
>
>    // rtlib->dump();
>
>    void * main_fp = jit->getPointerToFunction(rtlib->getFunction("main"));
>
>    int32_t (*target_program)() = (int32_t(*)())(intptr_t)(main_fp);
>
>    std::cout << "Ready..." << std::endl;
>
>    return target_program();
>
>    #if 0
>
>    // Write a bitcode file and interpret it.
>
>    {
>
>      std::string err;
>
>      llvm::raw_fd_ostream fout("sprite-out.bc", err,
> llvm::raw_fd_ostream::F_Binary);
>
>      llvm::WriteBitcodeToFile(module_stab.module_ir.ptr(), fout);
>
>    }
>
>    std::system("llvm-link-3.3 sprite-out.bc " SPRITE_LIBINSTALL
> "/sprite-rt.bc > tmp.bc");
>
>    std::system("mv tmp.bc sprite-out.bc");
>
>    int const status = std::system("lli-3.3 sprite-out.bc");
>
>    return WEXITSTATUS(status);
>
>    #endif
>
> }
>
> ####################
>
> define linkonce void @.step.myappend(%"struct.sprite::compiler::node"*
> %root_p) {
>
> .entry:
>
>    %0 = alloca %"struct.sprite::compiler::node"*
>
>    %1 = alloca %"struct.sprite::compiler::node"*
>
>    store %"struct.sprite::compiler::node"* %root_p,
> %"struct.sprite::compiler::node"** %0
>
>    %2 = load %"struct.sprite::compiler::node"** %0
>
>    %3 = getelementptr %"struct.sprite::compiler::node"* %2, i32 0, i32 2
>
>    %4 = load i8** %3
>
>    %5 = bitcast i8* %4 to %"struct.sprite::compiler::node"*
>
>    store %"struct.sprite::compiler::node"* %5,
> %"struct.sprite::compiler::node"** %0
>
>    br label %11
>
> ; <label>:6                                       ; preds = %11
>
>    %7 = load %"struct.sprite::compiler::node"** %0
>
>    %8 = getelementptr %"struct.sprite::compiler::node"* %7, i32 0, i32 2
>
>    %9 = load i8** %8
>
>    %10 = bitcast i8* %9 to %"struct.sprite::compiler::node"*
>
>    store %"struct.sprite::compiler::node"* %10,
> %"struct.sprite::compiler::node"** %0
>
>    br label %11, !sprite.implied !0
>
> ; <label>:11                                      ; preds = %6, %.entry
>
>    %12 = load %"struct.sprite::compiler::node"** %0
>
>    %13 = getelementptr %"struct.sprite::compiler::node"* %12, i32 0, i32 1
>
>    %14 = load i64* %13
>
>    %15 = load i64* %13
>
>    %16 = icmp eq i64 %15, -3
>
>    br i1 %16, label %6, label %17
>
> ; <label>:17                                      ; preds = %11
>
>    %18 = load %"struct.sprite::compiler::node"** %0
>
>    store %"struct.sprite::compiler::node"* %18,
> %"struct.sprite::compiler::node"** %1
>
>    %19 = getelementptr %"struct.sprite::compiler::node"* %18, i32 0, i32 1
>
>    %20 = load i64* %19
>
>    %21 = add i64 %20, 4
>
>    %22 = getelementptr [6 x i8*]* @.jtable, i32 0, i64 %21
>
>    %23 = load i8** %22
>
>    indirectbr i8* %23, [label %24, label %26, label %36, label %38,
> label %44, label %66]
>
> ; <label>:24                                      ; preds = %26, %17
>
>    %25 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([16 x
> i8]* @.str21, i32 0, i32 0))
>
>    ret void, !case...FAIL !1
>
> ; <label>:26                                      ; preds = %26, %17
>
>    %27 = load %"struct.sprite::compiler::node"** %1
>
>    %28 = getelementptr %"struct.sprite::compiler::node"* %27, i32 0, i32 2
>
>    %29 = load i8** %28
>
>    %30 = bitcast i8* %29 to %"struct.sprite::compiler::node"*
>
>    store %"struct.sprite::compiler::node"* %30,
> %"struct.sprite::compiler::node"** %1
>
>    %31 = getelementptr %"struct.sprite::compiler::node"* %30, i32 0, i32 1
>
>    %32 = load i64* %31
>
>    %33 = add i64 %32, 4
>
>    %34 = getelementptr [6 x i8*]* @.jtable, i32 0, i64 %33
>
>    %35 = load i8** %34
>
>    indirectbr i8* %35, [label %24, label %26, label %36, label %38,
> label %44, label %66]
>
> ; <label>:36                                      ; preds = %26, %17
>
>    %37 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([18 x
> i8]* @.str22, i32 0, i32 0))
>
>    ret void, !case...CHOICE !1
>
> ; <label>:38                                      ; preds = %26, %17
>
>    %39 = load %"struct.sprite::compiler::node"** %1
>
>    %40 = getelementptr %"struct.sprite::compiler::node"* %39, i32 0, i32 0
>
>    %41 = load %"struct.sprite::compiler::vtable"** %40
>
>    %42 = getelementptr %"struct.sprite::compiler::vtable"* %41, i32 0, i32 4
>
>    %43 = load void (%"struct.sprite::compiler::node"*)** %42
>
>    tail call void %43(%"struct.sprite::compiler::node"* %39)
>
>    ret void
>
> ; <label>:44                                      ; preds = %26, %17
>
>    store %"struct.sprite::compiler::node"* %root_p,
> %"struct.sprite::compiler::node"** %0
>
>    %45 = load %"struct.sprite::compiler::node"** %0
>
>    %46 = getelementptr %"struct.sprite::compiler::node"* %45, i32 0, i32 3
>
>    %47 = load i8** %46
>
>    %48 = bitcast i8* %47 to %"struct.sprite::compiler::node"*
>
>    store %"struct.sprite::compiler::node"* %48,
> %"struct.sprite::compiler::node"** %0
>
>    br label %54
>
> ; <label>:49                                      ; preds = %54
>
>    %50 = load %"struct.sprite::compiler::node"** %0
>
>    %51 = getelementptr %"struct.sprite::compiler::node"* %50, i32 0, i32 2
>
>    %52 = load i8** %51
>
>    %53 = bitcast i8* %52 to %"struct.sprite::compiler::node"*
>
>    store %"struct.sprite::compiler::node"* %53,
> %"struct.sprite::compiler::node"** %0
>
>    br label %54, !sprite.implied !0
>
> ; <label>:54                                      ; preds = %49, %44
>
>    %55 = load %"struct.sprite::compiler::node"** %0
>
>    %56 = getelementptr %"struct.sprite::compiler::node"* %55, i32 0, i32 1
>
>    %57 = load i64* %56
>
>    %58 = load i64* %56
>
>    %59 = icmp eq i64 %58, -3
>
>    br i1 %59, label %49, label %60
>
> ; <label>:60                                      ; preds = %54
>
>    %61 = load %"struct.sprite::compiler::node"** %0
>
>    %62 = bitcast %"struct.sprite::compiler::node"* %61 to i8*
>
>    %63 = getelementptr %"struct.sprite::compiler::node"* %root_p, i32 0,
> i32 0
>
>    store %"struct.sprite::compiler::vtable"* @.fwd.vt,
> %"struct.sprite::compiler::vtable"** %63
>
>    %64 = getelementptr %"struct.sprite::compiler::node"* %root_p, i32 0,
> i32 1
>
>    store i64 -3, i64* %64
>
>    %65 = getelementptr %"struct.sprite::compiler::node"* %root_p, i32 0,
> i32 2
>
>    store i8* %62, i8** %65
>
>    ret void
>
> ; <label>:66                                      ; preds = %26, %17
>
>    store %"struct.sprite::compiler::node"* %root_p,
> %"struct.sprite::compiler::node"** %0
>
>    %67 = load %"struct.sprite::compiler::node"** %0
>
>    %68 = getelementptr %"struct.sprite::compiler::node"* %67, i32 0, i32 2
>
>    %69 = load i8** %68
>
>    %70 = bitcast i8* %69 to %"struct.sprite::compiler::node"*
>
>    store %"struct.sprite::compiler::node"* %70,
> %"struct.sprite::compiler::node"** %0
>
>    br label %76
>
> ; <label>:71                                      ; preds = %76
>
>    %72 = load %"struct.sprite::compiler::node"** %0
>
>    %73 = getelementptr %"struct.sprite::compiler::node"* %72, i32 0, i32 2
>
>    %74 = load i8** %73
>
>    %75 = bitcast i8* %74 to %"struct.sprite::compiler::node"*
>
>    store %"struct.sprite::compiler::node"* %75,
> %"struct.sprite::compiler::node"** %0
>
>    br label %76, !sprite.implied !0
>
> ; <label>:76                                      ; preds = %71, %66
>
>    %77 = load %"struct.sprite::compiler::node"** %0
>
>    %78 = getelementptr %"struct.sprite::compiler::node"* %77, i32 0, i32 1
>
>    %79 = load i64* %78
>
>    %80 = load i64* %78
>
>    %81 = icmp eq i64 %80, -3
>
>    br i1 %81, label %71, label %82
>
> ; <label>:82                                      ; preds = %76
>
>    %83 = load %"struct.sprite::compiler::node"** %0
>
>    %84 = getelementptr %"struct.sprite::compiler::node"* %83, i32 0, i32 2
>
>    %85 = load i8** %84
>
>    %86 = bitcast i8* %85 to %"struct.sprite::compiler::node"*
>
>    store %"struct.sprite::compiler::node"* %86,
> %"struct.sprite::compiler::node"** %0
>
>    br label %92
>
> ; <label>:87                                      ; preds = %92
>
>    %88 = load %"struct.sprite::compiler::node"** %0
>
>    %89 = getelementptr %"struct.sprite::compiler::node"* %88, i32 0, i32 2
>
>    %90 = load i8** %89
>
>    %91 = bitcast i8* %90 to %"struct.sprite::compiler::node"*
>
>    store %"struct.sprite::compiler::node"* %91,
> %"struct.sprite::compiler::node"** %0
>
>    br label %92, !sprite.implied !0
>
> ; <label>:92                                      ; preds = %87, %82
>
>    %93 = load %"struct.sprite::compiler::node"** %0
>
>    %94 = getelementptr %"struct.sprite::compiler::node"* %93, i32 0, i32 1
>
>    %95 = load i64* %94
>
>    %96 = load i64* %94
>
>    %97 = icmp eq i64 %96, -3
>
>    br i1 %97, label %87, label %98
>
> ; <label>:98                                      ; preds = %92
>
>    %99 = load %"struct.sprite::compiler::node"** %0
>
>    %100 = bitcast %"struct.sprite::compiler::node"* %99 to i8*
>
>    %101 = call i8* @malloc(i64 32)
>
>    %102 = bitcast i8* %101 to %"struct.sprite::compiler::node"*
>
>    store %"struct.sprite::compiler::node"* %root_p,
> %"struct.sprite::compiler::node"** %0
>
>    %103 = load %"struct.sprite::compiler::node"** %0
>
>    %104 = getelementptr %"struct.sprite::compiler::node"* %103, i32 0, i32 2
>
>    %105 = load i8** %104
>
>    %106 = bitcast i8* %105 to %"struct.sprite::compiler::node"*
>
>    store %"struct.sprite::compiler::node"* %106,
> %"struct.sprite::compiler::node"** %0
>
>    br label %112
>
> ; <label>:107                                     ; preds = %112
>
>    %108 = load %"struct.sprite::compiler::node"** %0
>
>    %109 = getelementptr %"struct.sprite::compiler::node"* %108, i32 0, i32 2
>
>    %110 = load i8** %109
>
>    %111 = bitcast i8* %110 to %"struct.sprite::compiler::node"*
>
>    store %"struct.sprite::compiler::node"* %111,
> %"struct.sprite::compiler::node"** %0
>
>    br label %112, !sprite.implied !0
>
> ; <label>:112                                     ; preds = %107, %98
>
>    %113 = load %"struct.sprite::compiler::node"** %0
>
>    %114 = getelementptr %"struct.sprite::compiler::node"* %113, i32 0, i32 1
>
>    %115 = load i64* %114
>
>    %116 = load i64* %114
>
>    %117 = icmp eq i64 %116, -3
>
>    br i1 %117, label %107, label %118
>
> ; <label>:118                                     ; preds = %112
>
>    %119 = load %"struct.sprite::compiler::node"** %0
>
>    %120 = getelementptr %"struct.sprite::compiler::node"* %119, i32 0, i32 3
>
>    %121 = load i8** %120
>
>    %122 = bitcast i8* %121 to %"struct.sprite::compiler::node"*
>
>    store %"struct.sprite::compiler::node"* %122,
> %"struct.sprite::compiler::node"** %0
>
>    br label %128
>
> ; <label>:123                                     ; preds = %128
>
>    %124 = load %"struct.sprite::compiler::node"** %0
>
>    %125 = getelementptr %"struct.sprite::compiler::node"* %124, i32 0, i32 2
>
>    %126 = load i8** %125
>
>    %127 = bitcast i8* %126 to %"struct.sprite::compiler::node"*
>
>    store %"struct.sprite::compiler::node"* %127,
> %"struct.sprite::compiler::node"** %0
>
>    br label %128, !sprite.implied !0
>
> ; <label>:128                                     ; preds = %123, %118
>
>    %129 = load %"struct.sprite::compiler::node"** %0
>
>    %130 = getelementptr %"struct.sprite::compiler::node"* %129, i32 0, i32 1
>
>    %131 = load i64* %130
>
>    %132 = load i64* %130
>
>    %133 = icmp eq i64 %132, -3
>
>    br i1 %133, label %123, label %134
>
> ; <label>:134                                     ; preds = %128
>
>    %135 = load %"struct.sprite::compiler::node"** %0
>
>    %136 = bitcast %"struct.sprite::compiler::node"* %135 to i8*
>
>    store %"struct.sprite::compiler::node"* %root_p,
> %"struct.sprite::compiler::node"** %0
>
>    %137 = load %"struct.sprite::compiler::node"** %0
>
>    %138 = getelementptr %"struct.sprite::compiler::node"* %137, i32 0, i32 3
>
>    %139 = load i8** %138
>
>    %140 = bitcast i8* %139 to %"struct.sprite::compiler::node"*
>
>    store %"struct.sprite::compiler::node"* %140,
> %"struct.sprite::compiler::node"** %0
>
>    br label %146
>
> ; <label>:141                                     ; preds = %146
>
>    %142 = load %"struct.sprite::compiler::node"** %0
>
>    %143 = getelementptr %"struct.sprite::compiler::node"* %142, i32 0, i32 2
>
>    %144 = load i8** %143
>
>    %145 = bitcast i8* %144 to %"struct.sprite::compiler::node"*
>
>    store %"struct.sprite::compiler::node"* %145,
> %"struct.sprite::compiler::node"** %0
>
>    br label %146, !sprite.implied !0
>
> ; <label>:146                                     ; preds = %141, %134
>
>    %147 = load %"struct.sprite::compiler::node"** %0
>
>    %148 = getelementptr %"struct.sprite::compiler::node"* %147, i32 0, i32 1
>
>    %149 = load i64* %148
>
>    %150 = load i64* %148
>
>    %151 = icmp eq i64 %150, -3
>
>    br i1 %151, label %141, label %152
>
> ; <label>:152                                     ; preds = %146
>
>    %153 = load %"struct.sprite::compiler::node"** %0
>
>    %154 = bitcast %"struct.sprite::compiler::node"* %153 to i8*
>
>    %155 = getelementptr %"struct.sprite::compiler::node"* %102, i32 0, i32 0
>
>    store %"struct.sprite::compiler::vtable"* @.vtable.for.myappend,
> %"struct.sprite::compiler::vtable"** %155
>
>    %156 = getelementptr %"struct.sprite::compiler::node"* %102, i32 0, i32 1
>
>    store i64 -1, i64* %156
>
>    %157 = getelementptr %"struct.sprite::compiler::node"* %102, i32 0, i32 2
>
>    store i8* %136, i8** %157
>
>    %158 = getelementptr %"struct.sprite::compiler::node"* %102, i32 0, i32 3
>
>    store i8* %154, i8** %158
>
>    %159 = getelementptr %"struct.sprite::compiler::node"* %root_p, i32
> 0, i32 0
>
>    store %"struct.sprite::compiler::vtable"* @.vt.CTOR.MyCons,
> %"struct.sprite::compiler::vtable"** %159
>
>    %160 = getelementptr %"struct.sprite::compiler::node"* %root_p, i32
> 0, i32 1
>
>    store i64 1, i64* %160
>
>    %161 = getelementptr %"struct.sprite::compiler::node"* %root_p, i32
> 0, i32 2
>
>    store i8* %100, i8** %161
>
>    %162 = getelementptr %"struct.sprite::compiler::node"* %root_p, i32
> 0, i32 3
>
>    store i8* %101, i8** %162
>
>    ret void
>
> }
>
>
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>




More information about the llvm-dev mailing list