Giter VIP home page Giter VIP logo

inkwell's People

Contributors

bitwalker avatar cdisselkoen avatar corbanvilla avatar cpdt avatar dcnick3 avatar dependabot-preview[bot] avatar endorpersand avatar ericlbuehler avatar fawaztirmizi avatar folkertdev avatar gavrilikhin-d avatar ghaith avatar hywan avatar krout0n avatar meteor-lsw avatar michael-f-bryan avatar nbaksalyar avatar nlewycky avatar pat-lafon avatar rreverser avatar rtfeldman avatar seanyoung avatar supercilex avatar syrusakbary avatar taquangtrung avatar tfzee avatar thedan64 avatar tylanphear avatar willtunnels avatar ytoml avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

inkwell's Issues

`Module::print_to_file` creates the wrong file or panics.

Describe the Bug
Module::print_to_file creates the wrong file or panics.

To Reproduce

use inkwell::targets::Target;
use inkwell::targets::InitializationConfig;
use inkwell::context::Context;
use std::path::Path;

fn main() {
    Target::initialize_native(&InitializationConfig::default()).unwrap();
    let context = Context::create();
    let module = context.create_module("test");
    module.print_to_file(Path::new("test.ll")).unwrap();
}

Expected Behavior
Should create file test.txt, creates file test.txtDid not find a valid Unicode path stringcalled ``Result::unwrap()`` on an ``Err`` value: instead.

LLVM Version:

  • LLVM Version: 6.0
  • Inkwell Branch Used: llvm6-0

Rust version:

  • nightly-x86_64-unknown-linux-gnu
  • rustc 1.33.0-nightly (b2b7a063a 2019-01-01)

Desktop:

  • OS: Linux Mint 19.1

Additional Context
Simple fix was calling Path::new("test.ll\0") instead.

Not sure if this actually fix the problem, or if it's just working for now.

Linker error for doc tests on Travis-CI

Had to mark certain doc tests as no_run because they were throwing a linking error on travis (possibly due to LLVM?) I could not reproduce on either of my local machines.

Segmentation fault when calling Builder::build_global_string

When playing around with inkwell before starting my project in full, I decided to try to make a hello world program using it. This is the code that I came up with

extern crate inkwell;

use inkwell::context::Context;
use inkwell::targets::{InitializationConfig, Target};
use inkwell::AddressSpace;
use inkwell::module::Linkage;


fn main() {
    Target::initialize_native(&InitializationConfig::default()).unwrap();
    let ctx = Context::create();
    let module = ctx.create_module("program");
    let builder = ctx.create_builder();

    let str_type = ctx.i8_type().ptr_type(AddressSpace::Generic);
    let i32_type = ctx.i32_type();

    let global = builder.build_global_string("Hello, World!", "message");

    let printf_type = i32_type.fn_type(&[&str_type], true);
    let printf = module.add_function("printf", &printf_type, Some(&Linkage::ExternalLinkage));

    let main_fn_type = i32_type.fn_type(&[&i32_type, &str_type.ptr_type(AddressSpace::Generic)], false);

    let main_fn = module.add_function("main", &main_fn_type, None);
    let block = ctx.append_basic_block(&main_fn, "entry");
    builder.position_at_end(&block);
    builder.build_call(&printf, &[&global], "", false);
    builder.build_return(Some(&i32_type.const_int(0, false)));

    println!("{:?}", module.print_to_string());
}

It seems like it should work, however there's a segmentation fault when I call builder.build_global_string. The same happens with builder.build_global_string_ptr

Environment

Operating system: Arch Linux
Kernel version: 4.15.3-1-ARCH
LLVM version: 5.0.1-2
Inkwell version: 0.1.0#eafca272
rustc -vV output:

rustc 1.25.0-nightly (3ec5a99aa 2018-02-14)
binary: rustc
commit-hash: 3ec5a99aaa0084d97a9e845b34fdf03d1462c475
commit-date: 2018-02-14
host: x86_64-unknown-linux-gnu
release: 1.25.0-nightly
LLVM version: 6.0

Add wrappers for support functions

It would be nice to have "Rust-friendly" (I doubt "safe" is a good word) wrappers around the methods found in llvm_sys::support, namely:

  • LLVMAddSymbol
  • LLVMSearchForAddressOfSymbol
  • LLVMLoadLibraryPermanently
  • LLVMParseCommandLineOptions (a bit less useful)

However, I can't make it work in any way. I created support.rs with the following content, but I can't make a single test that actually succeeds.

use llvm_sys::support::*;
use libc::{c_void};
use std::ffi::CString;

pub fn add_symbol(name: &str, value: *const ()) {
    let name = CString::new(name).unwrap();

    unsafe {
        LLVMAddSymbol(name.as_ptr(), ::std::mem::transmute(value));
    }
}

pub fn search_for_address_of_symbol<T>(name: &str) -> Option<*mut T> {
    let name = CString::new(name).unwrap();

    unsafe {
        let addr = LLVMSearchForAddressOfSymbol(name.as_ptr());

        if addr.is_null() {
            None
        } else {
            Some(addr as *mut T)
        }
    }
}

pub fn load_library_permanently(filename: &str) -> bool {
    let filename = CString::new(filename).unwrap();

    unsafe {
        LLVMLoadLibraryPermanently(filename.as_ptr()) == 1
    }
}

I also tried the following for add_symbol, which didn't work either.

pub fn add_symbol<T>(name: &str, value: &mut T) {
    let name = CString::new(name).unwrap();

    let addr1 = &*value as *const _ as *const c_void;
    let addr2 = value as *const _ as *const ();

    unsafe {
        LLVMAddSymbol(name.as_ptr(),  value as &mut _ as &mut c_void);
    }
}

Support for multithreading

IIRC LLVM supports multithreading. We should support this at some point, if possible. It will likely have it's own set of obstacles. Any Rc types will likely need to be changed to Arc and our existing memory model may or may not need to be further reworked. This is for the far future, so I am marking it as v0.3.0 for now.

Documention

  • Full documentation:
    • attributes.rs: 8ecc815
    • basic_block.rs: ed7175c
    • builder.rs
    • comdat.rs: e185481
    • context.rs: e4c218c
    • data_layout.rs
    • debug_info.rs
    • execution_engine.rs
    • lib.rs
    • memory_buffer.rs
    • module.rs: 28a1de3
    • object_file.rs
    • passes.rs
    • support/
      • error_handling.rs: 8ecc815
      • mod.rs
    • targets.rs
    • types/
    • values/
      • array_value.rs e4fc903
      • basic_value_use.rs
      • call_site_value.rs: ff941af
      • enums.rs
      • float_value.rs
      • fn_value.rs
      • generic_value.rs
      • global_value.rs
      • instruction_value.rs
      • int_value.rs
      • metadata_value.rs
      • mod.rs
      • phi_value.rs
      • ptr_value.rs
      • struct_value.rs
      • traits.rs
      • vec_value.rs
  • Tari's example converted to Inkwell in the README
  • Google Sheet Notes on what is or isn't supported yet: link
  • Complete a brief (general overview) CHANGELOG.md for 0.1.0
  • Kaleidoscope example
  • Docs on GH pages: https://thedan64.github.io/inkwell/

GlobalValue almost unusable

Hey, I noticed the GlobalValue struct cannot be used with Builder methods, because it does not implement BasicType.
I also don't notice a function to get a PointerValue from a GlobalValue.

Unless I'm missing something, this should probably get fixed.

FunctionValue.as_any_value_enum() return PointerValue variant.

Bug description: The AnyValue implementation for FunctionValue returns an AnyValueEnum::PointerValue variant instead of a AnyValueEnum::FunctionValue variant.

Code to reproduce:

# src/main.rs
use inkwell::context::Context;
use inkwell::values::{AnyValue, AnyValueEnum};

fn main() {
    let context = Context::create();
    let module = context.create_module("fn_or_ptr");
    let fn_type = context.f32_type().fn_type(&[], false);
    let function_value = module.add_function("fn_or_ptr", fn_type, None);
    dbg!(function_value);
    dbg!(function_value.as_any_value_enum());
    dbg!(AnyValueEnum::FunctionValue(function_value));
}

# Cargo.toml
[dependencies]
inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" }

This produces the following output:

[src/main.rs:8] function_value = FunctionValue {
    name: "fn_or_ptr",
    address: 0x00007fe656c17128,
    is_const: true,
    is_null: false,
    llvm_value: "\ndeclare float @fn_or_ptr()\n",
    llvm_type: "float ()*"
}
[src/main.rs:9] function_value.as_any_value_enum() = PointerValue(
    PointerValue {
        ptr_value: Value {
            name: "fn_or_ptr",
            address: 0x00007fe656c17128,
            is_const: true,
            is_null: false,
            is_undef: false,
            llvm_value: "\ndeclare float @fn_or_ptr()\n",
            llvm_type: "float ()*"
        }
    }
)
[src/main.rs:10] AnyValueEnum::FunctionValue(function_value) = FunctionValue(
    FunctionValue {
        name: "fn_or_ptr",
        address: 0x00007fdf15c17128,
        is_const: true,
        is_null: false,
        llvm_value: "\ndeclare float @fn_or_ptr()\n",
        llvm_type: "float ()*"
    }
)

Expected output: function_value.as_any_enum_value() should return a AnyValueEnum::FunctionValue variant.

LLVM version: 7.0.1
Rust version: rustc 1.33.0 (2aa4c46cf 2019-02-28)

Also, unrelated, why aren't methods get_name, print_to_string, is_null, etc., part of the AnyValue trait? This forces casting AnyValueEnums into the correct Value type (using as_<type>_value() to call any of those methods. I imagine that in many cases it's possible to know the type of the value, but would just require explicit code duplication or manual matching.

Should be able to call function pointers

Is your feature request related to a problem? Please describe.
You should be able to call function pointers like you can call a FunctionValue.

Describe the solution you'd like
TBD. Either a PointerValue should be possible to convert to a FunctionValue if LLVM lets us, or the build_call method should be able to take either type.

Describe possible drawbacks to your solution
The second option might be a bit clunky if it has to take an Either enum as input.

Describe alternatives you've considered
None other than those two

Additional context
N/A

AddressSpace is not used everywhere

Some methods accept u32 as arguments instead of AddressSpace. An integer does not represent well what the target address space is, which is why the AddressSpace enum should be used instead.

(PR incoming)

Sub-Types (Type Safety v1.1)

WARNING: Brain dump ahead!

Today, build_int_add looks approximately like build_int_add(&self, left: &IntValue, right: &IntValue) -> IntValue. This is great, because it'll stop you from trying to add a FloatValue and an IntValue, for instance which would not work in LLVM. But I wonder if we can take type checking a step further! What happens when left is a u8 and right is a u16? Needs to be verified, but I believe this is also a LLVM error because it doesn't make much sense. How would adding two values of different sizes work (without casting)?

Therefore, I wonder if we can add sub-type annotations using generics (here-on known as sub-types). For example, IntType<u32> and IntValue<u32> so that you could express something like: build_int_add<T>(&self, left: &IntValue<T>, right: &IntValue<T>) -> IntValue<T> which would ensure only the same sub-types are added together when needed. So, IntValue<u8> and IntValue<u8> would be able to be added together but it'd prevent IntValue<u8> and IntValue<u16> from being added together, requiring a cast first. And, in case you do want different sub-types to be valid input you would just specify separate type variables: do_foo<L, R>(&self, left: &IntType<L>, right: &IntType<R>)

In terms of implementation details, the sub-type should basically just be a marker and not take up any additional space (as PhantomData if needed) (type parameters are cool!)

Outstanding questions:

  • How would custom & 80 bit width types be handled given that they don't map to rust types (yet?)? It may be permissible to disallow custom & 80 bit types since they are far less common. Or just find some workaround. i128 is stable; we can use custom type for the f128 and f80, etc I think.
  • usize should probably be a valid sub-type for ints, but I wonder if there's any issue with it's variable width nature? LLVM should allow us to map it to the pointer size at runtime LLVM has a pointer-width type
  • Signatures will quickly get verbose. Just imagine a simple String type: StructType<(PointerType<IntType<u8>>, IntType<usize>, IntType<usize>)> Will the compiler be able to hide most of this from the user so that they don't have to specify annotations themselves?
  • Could the num crate's traits help with float and int sub-types?
  • Should signed types be explicit(IE IntType<i8>) or just an irrelevant fact about an IntType<u8>? I'm guessing LLVM doesn't let you mix signed and unsigned addition without casting first, so I'm leaning towards keeping them explicit.

Provide `.into()` for converting PointerType to BasicTypeEnum

I wonder if we should provide .into() for converting PointerType to BasicTypeEnum. This is not an urgent issue because we can use .as_basic_type_enum() in the mean time.

Using .into() would make it more intuitive because converting other values to BasicValueEnum also uses .into().

Thank you!

Module does not hold reference to context

I noticed a major design flaw in the current implementation of modules.

The module needs to hold a reference to the context it was created in. Otherwise it's possible to drop the context before dropping the module, which will result in undefined behaviour.
I just ran into the error in a toy compiler I'm building.

The same also applies to Builder and its Context.

The easiest way to implement this is probably by having a member Rc<Context> in Module and Builder

Add additional compile time type safety to math instructions

This is a follow up to #45

We should constrain FloatMathValue & IntMathValue (names pending) to be implemented only for Vectors that have a numeric subtype, that is, IntValue<IntSize> and VectorValue<IntValue<IntSize>, VectorSize> for example.

If IntSize & VectorSize are not yet possible due to requiring const generics for example, we should split that off into a new issue for v0.3.0 and just implement for IntValue and VectorValue<IntValue> (and likewise for floats). See discussion in #45 for more info

Roll up type and value trait definitions into existing macro

As of #22, value and type trait definitions are no longer a part of the trait macro. It would be great to roll this all back up into the macro, but this would probably require procedural macros (at the very least for converting the associated enum type into a snake case method, if not more). Procedural macros only support derives right now IIRC and require a separate crate, both of which aren't ideal. Maybe we can hardcode the method name into the regular macro invocation to avoid the trouble...

I'm imagining something like:

trait_type_set! {
    /// Represents any LLVM type.
    AnyType requires AsTypeRef + Debug enumerated by AnyTypeEnum [
        BasicTypeEnum, IntType, FunctionType, FloatType, PointerType, StructType, ArrayType, VoidType, VectorType
    ]
}

Which would expand to:

/// Represents any LLVM type.
pub trait AnyType: AsTypeRef + Debug {
    /// Returns a `AnyTypeEnum` that represents the current type.
    fn as_any_type_enum(&self) -> AnyTypeEnum {
        AnyTypeEnum::new(self.as_type_ref())
    }
}

along with the trait impls for each provided type.

This isn't a big deal, but would make traits more DRY, so I'm leaving this as a wishlist item.

Create a custom attribute to reduce cfg boilerplate

Since proc macros will mostly be stabilized in the upcoming rust version 1.30, we should replace as much of the cfg boilerplate as possible with something clearer and easier to maintain.

For example,
#[cfg(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9", feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0"))]
could be represented as
#[feature_versions("llvm3-6" => "llvm6-0")]

and

#[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9")]
could be represented as
#[feature_versions("llvm4-0" => latest)]

This will, unfortunately, lock us into rustc 1.30+, but I think this is a price worth paying given the amount of cfg boilerplate which will only continue to grow with the current approach.

Unfortunately, even with proc macro stabilization, attributes still aren't allowed on everything, so some things like blocks and match arms might need to stay with the current cfg format.

...And the end goal being that once we are able to transition them all to this new format, one day, we can add usable cfg features that aren't at all related to the LLVM version, which will be neat!

Look into ways get_function_address could safely return a function

Currently it returns an address value pointer, which is in itself safe - but to actually use it, the user needs to unsafely transmute it into a rust extern "C" function. I'm wondering if this could be accomplished under the hood by "deserializing" the function's FunctionType (which has all of the needed type info) into rust types. Maybe writing a Serde plugin could help when it comes to complex types like StructType & PointerType.

Will probably need to account for edge cases - is VoidType deserializable? If so, would that just be () and is that ever useful? Is *() / &() valid in rust? Etc

Improved CI Story on non-Linux OSes

This will probably be a lot of work for Windows, but it'd be great to run tests against OSx in Travis and against Windows with Appveyor.

  • Linux
  • OSx
  • Windows

Should also add the Appveyor badge to the README.md and Cargo.toml

GEP is actually unsafe

In an attempt to get around #32, I've been trying to get a program working that can call printf with a string array. Looking at working IR, I see that to convert from an array to a pointer, an inbounds GEP instruction is used. This is the code I came up with to replicate that.

extern crate inkwell;
extern crate pest;

use inkwell::context::Context;
use inkwell::targets::{InitializationConfig, Target};
use inkwell::AddressSpace;
use inkwell::module::Linkage;
use inkwell::values::IntValue;

use std::path::Path;

fn main() {
    Target::initialize_native(&InitializationConfig::default()).unwrap();
    let ctx = Context::create();
    let module = ctx.create_module("program");
    let builder = ctx.create_builder();

    let str_type = ctx.i8_type().ptr_type(AddressSpace::Generic);
    let i32_type = ctx.i32_type();

    let my_message = "Hello, World!\n\0";
    let arr_type = ctx.i8_type().array_type(my_message.len() as u32);

    let mut chars = Vec::with_capacity(my_message.len());

    for ch in my_message.chars() {
        chars.push(ctx.i8_type().const_int(ch as u64, false));
    }

    let global = module.add_global(&arr_type, Some(AddressSpace::Generic), "message");
    let oof: Vec<&IntValue> = chars.iter().map(|x| x).collect();

    let str_array = arr_type.const_array(&oof[..]);

    global.set_initializer(&str_array);

    let printf_type = i32_type.fn_type(&[&str_type], true);
    let printf = module.add_function("printf", &printf_type, Some(&Linkage::ExternalLinkage));

    let main_fn_type = i32_type.fn_type(&[&i32_type, &str_type.ptr_type(AddressSpace::Generic)], false);

    let main_fn = module.add_function("main", &main_fn_type, None);
    let block = ctx.append_basic_block(&main_fn, "entry");
    builder.position_at_end(&block);

    let value = builder.build_in_bounds_gep(&global.as_pointer_value(), &oof[..], "");

    builder.build_call(&printf, &[&value], "", false);
    builder.build_return(Some(&i32_type.const_int(0, false)));

//    println!("{:?}", module.print_to_string());
    module.print_to_file(Path::new("test.ll"));
}

At the line where value is bound, the program exits with a SIGSEGV

Environment

Operating system: Arch Linux
Kernel version: 4.15.3-1-ARCH
LLVM version: 5.0.1-2
Inkwell version: 0.1.0#eafca272
rustc -vV output:

rustc 1.25.0-nightly (3ec5a99aa 2018-02-14)
binary: rustc
commit-hash: 3ec5a99aaa0084d97a9e845b34fdf03d1462c475
commit-date: 2018-02-14
host: x86_64-unknown-linux-gnu
release: 1.25.0-nightly
LLVM version: 6.0

tests do fail on os x

Describe the Bug

  • test_default_target_triple fails to compile on OS X as it only has a case for linux .
  • test_target_data fails on os x as the data layout differs.

To Reproduce
Run cargo test on os x

Expected Behavior
Tests pass

LLVM Version (please complete the following information):
(not related)

  • LLVM Version: 6.0
  • Inkwell Branch Used: llvm6-0

Desktop (please complete the following information):

  • OS: OS X

Double-free when dropping module as part of execution engine

Describe the Bug
Current relationship between execution engine and the module can lead to double-free of a module in a "safe" API usage.

To Reproduce

fn main() {
    Target::initialize_native(&InitializationConfig::default()).unwrap();
    let _execution_engine = {
        let context = Context::create();
        let module = context.create_module("sum");
        module.create_jit_execution_engine(OptimizationLevel::None).unwrap()
    };
}

Expected Behavior
Execution engine should either take ownership of the module or borrow it or module should be reference-counted internally or [use any other clear ownership semantic].

LLVM Version (please complete the following information):

  • LLVM Version: 7.0.0
  • Inkwell Branch Used: master

Desktop (please complete the following information):

  • OS: macOS 10.14 (Mojave)

Additional Context
FWIW another Rust wrapper for LLVM had and fixed the same issue: TomBebbington/llvm-rs#25

Test case failed when we use a llvm which enable LLVM_ENABLE_ASSERTIONS option

Describe the Bug
Test case failed when we use a llvm which enable LLVM_ENABLE_ASSERTIONS option.

cargo test --all --no-default-features --features "llvm7-0" --verbose
       Fresh lazy_static v1.3.0
       Fresh ucd-util v0.1.3
       Fresh semver-parser v0.7.0
       Fresh unicode-xid v0.1.0
       Fresh utf8-ranges v1.0.2
       Fresh cc v1.0.34
       Fresh unicode-xid v0.0.4
       Fresh quote v0.3.15
       Fresh either v1.5.2
       Fresh thread_local v0.3.6
       Fresh regex-syntax v0.6.6
       Fresh semver v0.9.0
       Fresh synom v0.11.3
       Fresh memchr v2.2.0
       Fresh proc-macro2 v0.4.27
       Fresh libc v0.2.51
       Fresh syn v0.11.11
       Fresh aho-corasick v0.7.3
       Fresh quote v0.6.11
       Fresh enum-methods v0.0.8
       Fresh regex v1.1.5
       Fresh syn v0.15.30
       Fresh inkwell_internal_macros v0.1.0 (/work/project/inkwell/internal_macros)
       Fresh llvm-sys v70.1.0
       Fresh inkwell v0.1.0 (/work/project/inkwell)
    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running `/work/project/inkwell/target/debug/deps/inkwell-710be66657a29f6e`

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running `/work/project/inkwell/target/debug/deps/all-feb08d9805fc64a7`

running 91 tests
all-feb08d9805fc64a7: /work/tool/llvm/source/70/llvm-7.0.1/lib/IR/AttributeImpl.h:129: llvm::IntAttributeImpl::IntAttributeImpl(llvm::Attribute::AttrKind, uint64_t): Assertion `(Kind == Attribute::Alignment || Kind == Attribute::StackAlignment || Kind == Attribute::Dereferenceable || Kind == Attribute::DereferenceableOrNull || Kind == Attribute::AllocSize) && "Wrong kind for int attribute!"' failed.
all-feb08d9805fc64a7: /work/tool/llvm/source/70/llvm-7.0.1/lib/IR/Instructions.cpp:310: void llvm::CallInst::init(llvm::FunctionType*, llvm::Value*, llvm::ArrayRef<llvm::Value*>, llvm::ArrayRef<llvm::OperandBundleDefT<llvm::Value*> >, const llvm::Twine&): Assertion `(Args.size() == FTy->getNumParams() || (FTy->isVarArg() && Args.size() > FTy->getNumParams())) && "Calling a function with bad signature!"' failed.
error: process didn't exit successfully: `/work/project/inkwell/target/debug/deps/all-feb08d9805fc64a7` (signal: 6, SIGABRT: process abort signal)

To Reproduce
Use a llvm which enable LLVM_ENABLE_ASSERTIONS option to test our test case, it failed.

In the following content, I will show in detail how I manually compiled llvm.

Expected Behavior

  1. Test case passed
  2. As a safety wrapper, inkwell should be tested in a LLVM_ENABLE_ASSERTIONS enabled llvm environment.
    This can help us to find many problems in advance, such as the number of incorrect parameters, the wrong parameter type, and the wrong range of values (especially when using integers instead of enum for some tests). These problems are encapsulated and often do not go wrong at compile time, but may cause a crash or panic when encountering some boundary conditions at runtime.

LLVM Version (please complete the following information):

  • LLVM Version: 7.0
  • Inkwell Branch Used: master

Desktop (please complete the following information):

  • OS: deepin linux 15.9.3

Additional Context
LLVM compiler and install.txt

Try out nightly renamed deps in Cargo.toml

Is your feature request related to a problem? Please describe.
The current version management story means we'd have to create separate crates for each llvm version, ie: inkwell-0.1.0-3_6, inkwell-0.1.0-7, etc. rust-lang/cargo#5653 might allow us to instead have a single crate that relies solely on the feature flags we already use today.

Describe the solution you'd like
For example this new cargo feature might allow us to instead do this

#[cfg(feature = "llvm3-6")]
extern crate llvm_sys_36 as llvm_sys;
#[cfg(feature = "llvm7-0")]
extern crate llvm_sys_70 as llvm_sys;

when Cargo.toml has:

[dependencies]
llvm_sys_36 = { package = "llvm-sys", version = "36.2.0" }
llvm_sys_70 = { package = "llvm-sys", version = "70.0.0" }

Describe possible drawbacks to your solution
None that I can think of; it would significantly improve the current approach for the end user (if it does indeed work this way).

Should support multiple LLVM-sys versions

Probably by feature toggle, and conditional compilation. Either default to latest or require a feature to be selected (if possible)

  • v3.6 (Initial support, usable)
  • v3.6 (Version specific features)
  • v3.7 (Initial support, usable)
  • v3.7 (Version specific features)
  • v3.8 (Initial support, usable)
  • v3.8 (Version specific features)
  • v3.9 (Initial support, usable)
  • v3.9 (Version specific features)
  • v4.0 (Initial support, usable)
  • v4.0 (Version specific features)
  • v5.0 (Initial support, usable)
  • v5.0 (Version specific features)
  • v6.0 (Initial support, usable)
  • v6.0 (Version specific features)
  • v7.0 (Initial support, usable)
  • v7.0 (Version specific features)
  • v8.0 (Initial support, usable)
  • v8.0 (Version specific features)
  • v9.0 (Initial support, usable)
  • v9.0 (Version specific features)
  • v10.0 (Initial support, usable)
  • v10.0 (Version specific features)

write_bitcode_to_file has inconsistent success

Locally, it seems to pass most of the time but will occasionally fail with an OS error saying the file descriptor is bad. (Ubuntu at least). Seems to fail more often on Travis (at least one job per build) so I've commented out the test for now and made the method private. It would be great to have someone more knowledgeable about filesystems (and possibly LLVM) take a look. It could possibly be a LLVM bug since the wrapper is really straightforward and thin. write_bitcode_to_path doesn't have this problem (different FFI function call, though)

Extern functions are not detected by Kaleidoscope JIT

Describe the Bug
As stated in the comment extern functions defined in Rust code are not detected by Kaleidoscope JIT.

To Reproduce

  1. Run Kaleidoscope REPL.
  2. Type extern printd(x)
  3. Type printd(10)
  4. Function returns NaN

Expected Behavior
printd function should have returned passed value and printed it.

LLVM Version (please complete the following information):

  • LLVM Version: 7.0.1
  • Inkwell Branch Used: llvm7-0

Desktop (please complete the following information):

  • OS: OS X

Additional Context
After a bit of investigation, it seems that there are a couple of problems here:

  1. rustc will mangle the names of those function unless #[no_mangle] attribute is applied.
  2. Unless those functions are used in the Rust code, the compiler will remove them. To avoid this they should be called somewhere or put into a static array with #[used] attribute like here.
  3. Currently, body that returns NaN is set for extern functions. This causes that functions that are defined in Rust are being overridden by those that return NaN (strangely, but functions like sin and cos are not being overridden). It seems that if we got extern definition, we should not attach any body to it.

I kinda fixed these issues in my fork, but it will segfault if extern function, that is not actually defined, is called. I'm not sure what is desired behavior here. Let me know what do you think about this.

Set Community Standards

  • Contributing.md
  • Code of Conduct.md
  • PR Template (ie document & test new methods)
  • Issue Template

Add Kaleidoscope step by step guide

I think it would be really helpful to also have the step by step guide to the kaleidoscope language with code for chapters separated, so you can see how it all comes together.

I'm willing to write it myself, if anyone wants to help that would be nice!

get_context isn't always safe

Describe the Bug
Somehow newer rust versions (late 2018+) expose unsafe behavior (maybe due to LTO?). Anyway, you can now delete a context when it goes out of scope and then call get_context for an easy segfault.

To Reproduce
Run this test:

// #[test]
// fn test_no_context_double_free2() {
// let context = Context::create();
// let int = context.i8_type();
// let context2 = int.get_context();
// fn move_(_: Context) {}
// move_(context);
// context2.i8_type().const_int(0, false);
// }

Expected Behavior
Test passes / no segfault

LLVM Version (please complete the following information):

  • LLVM Version: 7.0, possibly others
  • Inkwell Branch Used: 7-0, possibly others

Desktop (please complete the following information):

  • OS: Ubuntu 16.04

Additional Context
I think there are a couple options here:

  1. Types and Values should carry an RC to their context, so they can always dish out a safe context ref. The downside here is that types and values can no longer be Copy but the Clone is relatively cheap.

  2. We could have some global state manager which keeps track of when Context dies, and panic if the Context is attempted to be used.

  3. Have generated types and values have stricter references so that they are tied directly to their context and cannot escape so that a context is always valid while they are. This seems to be an unpopular choice.

  4. Make all such get_context methods unsafe methods

Support vector types in math operations

Is your feature request related to a problem? Please describe.
Yep -- in LLVM IR it is entirely valid to use mathematical operations on vector values, provided the two vectors have the same lengths and element type (and the element type is numeric, of course). However, all of Inkwell's math builder functions take and return IntValue or FloatValue values, meaning vectors can't easily be passed in without converting to a BasicValueEnum then back or using transmute.

Describe the solution you'd like
I'm not too sure what a solution would look like - a simple but messy solution might be to add functions like build_float_vec_add and build_int_vec_add, but you do lose the benefit of the typed parameters (although there's probably no way around that until #8 is resolved...)

I'm happy to make a pull request with the solution outlined above, although it's probably worth some discussion on a better alternative first?

Explore higher level macros

It'd be pretty neat if you could do something like:

let foo = function! {
    foo(a: u32, b: CustomStruct, c: Ptr<i32>) -> u32 {
        entry:
            a <- 3
            br end
        end:
            return 1;
    }
};

Which would return a function value or Result<FunctionValue, Box<Error>> with that definition. It might need to make some assumptions, like always using the global Context, though. Maybe you could optionally specify a context.

Dedupe tests in travis

Currently we're running tests once and then again when uploading codecoverage. We should combine this into one process and ideally have the codecoverage use the original test data.

Can't use builder which belongs to a different context

Describe the Bug
Somehow newer rust versions (late 2018+) expose unsafe behavior (maybe due to LTO?). Anyway, mixing and matching unrelated context and builder seems to produce a segfault.

To Reproduce
Uncomment this line and run test:

// builder.build_unreachable();

Expected Behavior
Successful test and no segfault

LLVM Version (please complete the following information):

  • LLVM Version: 7.0, probably others
  • Inkwell Branch Used: 7.0, probably others

Desktop (please complete the following information):

  • OS: Ubuntu 16.04

Additional Context
Not totally sure what to do about this one. I'm not sure there's a way to ensure builder is totally only used with objects of the same context, even at runtime?

Workaround libffi linking issue

Describe the Bug
Newer versions of LLVM have an issue where libffi doesn't get linked in automatically. I thought https://github.com/TheDan64/inkwell/blob/master/.cargo/config would fix the issue, but it only works when building inkwell locally. Using inkwell as a crate seems to surface the issue again. (Adding the config file to the project does work, but should not be necessary)

To Reproduce
Add inkwell as a dependency to a project and compile with it.

Expected Behavior
Should not have any linker issues when using inkwell.

LLVM Version (please complete the following information):

  • LLVM Version: 3.9+ IIRC
  • Inkwell Branch Used: llvm3-9+ IIRC

Desktop (please complete the following information):

  • OS: Ubuntu 16.04

Improve speed by moving function collections to stack arrays

A common pattern being used looks something like this:

fn inkwell_does_stuff(input: &[&InkwellValue]) {
    let mut input = Vec<LLVMValueRef> = input.iter().map(|val| val.as_value_ref()).collect(); 

    // call LLVM function with raw ptr to input
}

What we're basically doing is taking a bunch of our own types and mapping them to a sequence of raw llvm pointers. The problem is that Vec will allocate on the heap, but this sequence is only needed for the scope of the function and never gets directly returned. So, I think we can improve this pattern by using something like arrayvec which stores the contents on the stack. This should also work really well because we never modify the size of these vectors, just use them as an intermediate data location for LLVM to read from.

Alternatively, if there's a way to just collect into a a stack slice, that would work too.

This might make for a good first PR if anyone's interested since it doesn't require technical knowledge of LLVM, just Rust.

Improve different traits

Many traits actually exist, notably for values and types, but aren't used to their full potential.

Methods on traits

Most values declare the get_name and set_name methods, and implement if the exact same way. Yet, they all implement it individually. Using a single method bound to a trait may avoid code duplication.

Unsized trait

It is currently impossible to return BasicValue from a function, because it is unsized. Yet, all values that implement BasicValue have the exact same size. It would be nice to have a type which represents all built-in values, whilst having a known size.

Private types

The Value struct would be perfect for the above tasks, but it is currently private. Making it public and adding facilities, such as into_float_value, would be extremely useful; however, it would also be unsafe.

String termination issue in write_to_file

The path within the method write_to_file doesn't seem to convert to a null-terminated string correctly

The method is here: https://github.com/TheDan64/inkwell/blob/master/src/targets.rs#L870

Please see the discussion here: https://www.reddit.com/r/rust/comments/98d8tb/new_to_rust_can_anyone_help_me_with_this_problem/e4fqji8/

@daboross seems to figure out how to solve it.

Given that adding \0 fixes it, I think

LLVMTargetMachineEmitToFile(self.target_machine, module.module.get(), path.as_ptr() as *mut i8, file_type.as_llvm_file_type(), &mut err_string)
is the line causing this.
It is incorrectly sending a ptr to a rust &str to an FFI interface, where instead it should be turning it into a std::ffi::CString. CString would then guarantee there are no inner \0 bytes and that \0 is appended onto the end.

(I'm new to Rust (and C). So, I have a limited understanding of this issue)

Safe function wrapper

I know PR #36 has been merged long ago, but I've been looking to solve problem with safety of dynamic functions similar to one described in #5 and decided to see what Inkwell does here.

While the Symbol trick is nice, unfortunately I don't think it actually helps with safety issue of outliving backing storage at all - it's still way too easy to accidentally get and store a raw function instead of a wrapper Symbol by accidentally putting * in front of the call like

let func = {
  // ...
  let execution_engine = /* ... */;
  // ...
  *execution_engine.get_function::<MyFunc>("sum").unwrap()
};

Despite the wrapper and private traits like private::Sealed, this works without any warnings / errors because Rust performs Deref coercion (which is implemented on Symbol), which, in turn returns one of function types , which Rust believes to be safely Copyable, and so lifetime information is immediately lost.

Forgetting to call Target::initialize_native(...) causes segfault

Describe the Bug
Forgetting to call Target::initialize_native(...) when building a JIT compiler causes a spurious segfault deep inside of module.create_jit_execution_engine.

To Reproduce
The simplest way - take a standard example from jit.rs and comment out the first line in main function.

Expected Behavior
Return a Result-based error from create_jit_execution_engine.

LLVM Version (please complete the following information):

  • LLVM Version: 7.0.0
  • Inkwell Branch Used: master

Desktop (please complete the following information):

  • OS: macOS 10.14 (Mojave)

Additional Context
Relevant stacktrace:

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x6d)
  * frame #0: 0x0000000100324af9 jit`(anonymous namespace)::Verifier::verify() + 785
    frame #1: 0x0000000100324790 jit`llvm::verifyModule(llvm::Module const&, llvm::raw_ostream*, bool*) + 121
    frame #2: 0x0000000100180266 jit`LLVMVerifyModule + 119
    frame #3: 0x000000010000b030 jit`verify(self=<unavailable>) at module.rs:634
    frame #4: 0x000000010000b11a jit`clone(self=<unavailable>) at module.rs:1323
    frame #5: 0x000000010000ad06 jit`create_jit_execution_engine(self=<unavailable>, opt_level=<unavailable>) at module.rs:502
    frame #6: 0x0000000100001c89 jit`jit::run::h8ffc90d06f718914 + 153
    frame #7: 0x000000010000252d jit`jit::main::he623d44605966ec7 + 13

Attempt to fix travis-ubuntu specific LLVM 3.9 linking issues

Mentioned this issue in #39.

Linking error:

  = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/home/travis/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.12l21m8irplp66s9.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.16u6js6g0l3k1ic6.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.17w1aw0a8xomqusj.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.186ando3tuiv0oj6.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.1dmb1nz6dxo84fr9.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.1im38lueib99jsk0.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.1lconjl9u0o2i6n8.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.1mvmz58owquyropc.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.1oc9n4juaw7leig6.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.1pm9tuwz75jfwtvh.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.1rnxx9yo0hj048jp.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.1tljfcyuidnf5zxo.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.1tqc2b30yawnn5i2.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.1ts1eq5qo9lurzya.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.1v01qzz1n4emezqj.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.1wpjxmfbjfx7rpo4.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.1y16o1qfye96o7m0.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.1zeawhkbeobww1zn.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.23tqyymcb18u96mb.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.240rsvwmdh8r7j13.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.24jhsbw0ncmvj9j1.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.24uh6dq2md5dtxfk.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.25g5mu05s5npgqyj.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.26v5zgpr73c51cgt.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.27d9w197zt70k8t0.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.28jkdc27x4ysvi88.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.29gh7539pte0vrdy.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.2f0hry2t7c05ttdi.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.2g3psxo8la9bybb1.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.2gisywms6kf1159g.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.2gj5jgsr2ggya5sb.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.2imn4yrlwqo3impj.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.2k1mlyk0ashdwh9z.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.2k7kind2hxlzb2u3.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.2kjrmm4fe2aha78f.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.2lyh15q6cjwzy18c.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.2mvanq85curzotex.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.2rwf42k1fugd9hc4.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.2w0a1dc4ffhfth2d.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.2w28raebt29ztati.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.2zfihsw3brwk9aop.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.2zuafs7de0b5pp1u.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.315cowujok3bhx9x.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.3171x0bwu82dptu7.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.32nefjtmvg2podc0.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.330axegc3fzuflt0.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.35nxpq0n8ab43wow.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.362qmy20to2q2ams.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.3685hnm1xon16qcg.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.38ps4pa181wsnsy9.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.39yjckync58o447x.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.3ayaeypdcro9d6yk.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.3bsz47jb198orqlz.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.3cx7oljifvb206q7.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.3e34mlt2hlecgls2.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.3elefkzkv35bbvra.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.3gguq802c5to7syk.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.3i6v9k3dincmp7qo.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.3k3mg4hogn33pp4k.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.3kyxp6ea5wmb2udd.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.3oqznv5oym7l3m4e.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.3qp4v8qfz1tci1jd.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.3r4opcj7tzc3u5gf.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.3rdo75vri32rc6qy.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.3rngp6bm2u2q5z0y.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.3z06109zb8n7qzb8.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.41zoa35vc5gl4jal.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.436dotimmrgzkwfa.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.43v3t5lolad8sr9r.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.43v6g0y2xsxoggnt.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.44bsbddupzfao2om.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.45nf4z58qqykpcpi.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.45pc7c65foh9i35f.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.46qws1s9mss1n2al.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.48721dc4k5qxei0u.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.49a7n47po4ttqjl7.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.49lx1q7cxvpykyv0.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.4a6dgwgsyclvnmy1.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.4ezmh1vbs95c5ack.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.4jdnq7xfjeka1bt.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.4oa6ip27i9gyfkd7.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.4p4eg1cl3moa38mc.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.4rzh6npf1tuwcxx9.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.4w2dafjzpny21t81.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.4xq48u46a1pwiqn7.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.4yh8x2b62dcih00t.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.4ypvbwho0bu5tnww.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.5166lj5yjaf01mq6.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.51gj5xk7k5xgp9s3.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.51qtb7slcbtaqyx9.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.537kxwfmsw7p43hn.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.53q180006d33xlbp.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.54agbs21rcrx184d.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.54kmn83aqmdqzhl2.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.56dly8q07ws8ucdq.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.5710z7sqyh946040.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.57yblro7ni85x1su.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.5b1yrgtp2k5qeiwa.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.5eq4z56a11kfi8wm.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.5fk3etfycxvgepj8.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.5gf6du7k58s78kob.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.63mmpc50mjcb0lb.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.741kfx7klu8pun5.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.8xzrsc1ux72v29j.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.98g0d9x8aw3akpe.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.9elsx31vb4it187.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.9fcb3syd3ne5k0n.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.bt3hp3mbvtmem57.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.fr9tmu7ux84ruzp.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.ftpdosj3rolvck1.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.g7uim93sa35mmvy.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.kt25z0521ngsjub.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.m3zgcalg49ltet1.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.mz7vgmcf23rofcc.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.w044p5fd4hb9cy3.rcgu.o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.weai5lc96s7xfle.rcgu.o" "-o" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559" "/home/travis/build/TheDan64/inkwell/target/debug/deps/inkwell-fedb510211a7b559.crate.allocator.rcgu.o" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "-L" "/home/travis/build/TheDan64/inkwell/target/debug/deps" "-L" "/usr/lib/llvm-3.9/lib" "-L" "/home/travis/build/TheDan64/inkwell/target/debug/build/llvm-sys-e01cd8f8c7d44dab/out" "-L" "/home/travis/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-l" "ffi" "-Wl,-Bstatic" "/home/travis/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libtest-d35c28f0ef54928a.rlib" "/home/travis/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libterm-74d3aea795746522.rlib" "/home/travis/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libgetopts-a54c1e8819ad83c5.rlib" "/home/travis/build/TheDan64/inkwell/target/debug/deps/libllvm_sys-f3fa063abad631ce.rlib" "/home/travis/build/TheDan64/inkwell/target/debug/deps/libbitflags-2fb7b66d38f8668c.rlib" "/home/travis/build/TheDan64/inkwell/target/debug/deps/liblibc-6ffeacde403e5b40.rlib" "/home/travis/build/TheDan64/inkwell/target/debug/deps/libeither-0ce6ab9683f9b971.rlib" "/home/travis/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-c10c01f750e28d27.rlib" "/home/travis/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-428f111496747802.rlib" "/home/travis/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc_jemalloc-44df8b23e0916803.rlib" "/home/travis/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-fbadb5623ab8cc25.rlib" "/home/travis/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc_system-c7afd75849f41e4c.rlib" "/home/travis/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-42a81d0277a7a698.rlib" "/home/travis/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-20751df81794b150.rlib" "/home/travis/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd_unicode-34dbdc699982f60d.rlib" "/home/travis/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-8e8a91684c5e06e5.rlib" "/home/travis/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-4e85b1507e729192.rlib" "-Wl,-Bdynamic" "-l" "ffi" "-l" "rt" "-l" "dl" "-l" "tinfo" "-l" "pthread" "-l" "z" "-l" "m" "-l" "stdc++" "-l" "ffi" "-l" "util" "-l" "util" "-l" "ffi" "-l" "ffi" "-l" "dl" "-l" "rt" "-l" "pthread" "-l" "pthread" "-l" "gcc_s" "-l" "c" "-l" "m" "-l" "rt" "-l" "pthread" "-l" "util" "-l" "util"
  = note: /usr/bin/ld: /home/travis/build/TheDan64/inkwell/target/debug/deps/libllvm_sys-f3fa063abad631ce.rlib(ObjCARCOpts.cpp.o): unrecognized relocation (0x2a) in section `.text._ZN12_GLOBAL__N_110ObjCARCOptD2Ev'
          /usr/bin/ld: final link failed: Bad value
          collect2: error: ld returned 1 exit status

As best I can tell; this should not affect most Ubuntu users - seems to be specific to Travis-CI's ubuntu setup

impl Debug for all public facing types

In particular wrapper structs should have custom Debug impls that call relevant LLVM functions to provide additional info. Enums, in general, should just do #[derive(Debug)] unless there's a good reason for a custom Debug impl.

Checklist:

  • basic_blocks.rs
    • BasicBlock: Custom
  • targets.rs
    • CodeGenOptLevel: Derived
    • CodeModel: Derived
    • RelocMode: Derived
    • InitializationConfig: Derived
    • Target: Custom
    • TargetMachine: Custom
    • ByteOrdering: Derived
    • TargetData: Custom
  • module.rs
    • Linkage: Derived
    • Module: Custom
  • execution_engine.rs
    • FunctionLookupError: Derived
    • ExecutionEngine: Custom
  • values/enums.rs
    • AggregateValueEnum: Derived
    • AnyValueEnum: Derived
    • BasicValueEnum: Derived
    • BasicMetadataValueEnum: Derived
  • values/instruction_value.rs
    • InstructionOpcode: Derived
    • InstructionValue: Custom
  • types/enums.rs
    • AnyValueEnum: Derived
    • BasicValueEnum: Derived
  • values/int_value.rs
    • IntValue: Custom
  • values/phi_value.rs
    • PhiValue: Custom
  • values/struct_value.rs
    • StructValue: Custom
  • values/array_value.rs
    • ArrayValue: Custom
  • values/float_value.rs
    • FloatValue: Custom
  • values/fn_value.rs
    • FunctionValue: Custom
    • ParamValueIter: Custom
  • values/metadata_value.rs
    • MetadataValue: Custom
  • values/ptr_value.rs
    • PointerValue: Custom
  • values/vec_value.rs
    • VectorValue: Custom
  • data_layout.rs
    • DataLayout: Custom
  • context.rs
    • Context: Custom
    • ContextRef: Derived
  • memory_buffer.rs
    • MemoryBuffer: Custom
  • builder.rs
    • Builder: Custom
  • object_file.rs
    • ObjectFile: Custom
    • SectionIterator: Custom
    • Section: Custom
    • RelocationIterator: Custom
    • Relocation: Custom
    • SymbolIterator: Custom
    • Symbol: Custom
  • passes.rs
    • PassManager: Custom
    • PassManagerBuilder: Custom
    • PassRegistry: Custom
  • types/array_type.rs
    • ArrayType: Custom
  • types/float_type.rs
    • FloatType: Custom
  • types/fn_type.rs
    • FunctionType: Custom
  • types/vec_type.rs
    • VecType: Custom
  • types/ptr_type.rs
    • PointerType: Custom
  • types/struct_type.rs
    • StructType: Custom
  • types/void_type.rs
    • VoidType: Custom
  • types/int_type.rs
    • IntType: Custom

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.