thedan64 / inkwell Goto Github PK
View Code? Open in Web Editor NEWIt's a New Kind of Wrapper for Exposing LLVM (Safely)
Home Page: https://thedan64.github.io/inkwell/
License: Apache License 2.0
It's a New Kind of Wrapper for Exposing LLVM (Safely)
Home Page: https://thedan64.github.io/inkwell/
License: Apache License 2.0
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)
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.
Should also add the Appveyor badge to the README.md
and Cargo.toml
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:
inkwell/tests/all/test_context.rs
Lines 19 to 30 in b84df07
Expected Behavior
Test passes / no segfault
LLVM Version (please complete the following information):
Desktop (please complete the following information):
Additional Context
I think there are a couple options here:
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.
We could have some global state manager which keeps track of when Context
dies, and panic if the Context
is attempted to be used.
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.
Make all such get_context
methods unsafe methods
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
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).
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.
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);
}
}
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
Describe the Bug
As stated in the comment extern functions defined in Rust code are not detected by Kaleidoscope JIT.
To Reproduce
extern printd(x)
printd(10)
NaN
Expected Behavior
printd
function should have returned passed value and printed it.
LLVM Version (please complete the following information):
Desktop (please complete the following information):
Additional Context
After a bit of investigation, it seems that there are a couple of problems here:
rustc
will mangle the names of those function unless #[no_mangle]
attribute is applied.#[used]
attribute like here.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.
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 impl
s 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.
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
is the line causing this.Line 875 in 638306f
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)
There's a trend of creating elegant yet simple websites for rust libraries. It's worth considering, once we've made enough progress.
See, for example:
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!
Many traits actually exist, notably for values and types, but aren't used to their full potential.
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.
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.
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.
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?
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):
Desktop (please complete the following information):
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
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)
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
LLVM Version (please complete the following information):
Desktop (please complete the following information):
Additional Context
LLVM compiler and install.txt
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!
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!
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 AnyValueEnum
s 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.
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
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:
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
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 Copy
able, and so lifetime information is immediately lost.
Rust does this for their Value types and LLVM suggests Types are singletons. Although Values don't seem to be singletons, this should still be safe to do.
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):
Desktop (please complete the following information):
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
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
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
Probably by feature toggle, and conditional compilation. Either default to latest or require a feature to be selected (if possible)
And add codecov badge to README
Does this library support the LLVM interpreter, out of curiosity? http://llvm.org/doxygen/classllvm_1_1Interpreter.html
...Seems to have broken when upgrading to LLVM 6: https://travis-ci.org/TheDan64/inkwell/jobs/390568849
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.
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):
Desktop (please complete the following information):
Additional Context
FWIW another Rust wrapper for LLVM had and fixed the same issue: TomBebbington/llvm-rs#25
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.
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:
Rust version:
Desktop:
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.
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.
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.
Apparently this broke some while ago and doesn't seem to have no sudo support anymore? Maybe we should move away from (straight) kcov :/
Some options:
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)
Desktop (please complete the following information):
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.
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:
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 runtimeString
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?num
crate's traits help with float and int sub-types?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.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:
inkwell/tests/all/test_builder.rs
Line 441 in b84df07
Expected Behavior
Successful test and no segfault
LLVM Version (please complete the following information):
Desktop (please complete the following information):
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?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.