Giter Site home page Giter Site logo

anydsl / impala Goto Github PK

View Code? Open in Web Editor NEW
150.0 41.0 12.0 7.96 MB

An imperative and functional programming language

Home Page: https://anydsl.github.io

License: GNU General Public License v3.0

CMake 1.67% C++ 91.09% Python 6.10% Shell 0.03% C 1.12%
compiler imperative-programming-language functional-language continuation-passing-style domain-specific-language partial-evaluators gpu cpu vectorization simd

impala's Introduction

impala's People

Contributors

fbenz avatar hugobros3 avatar klaasb avatar leissa avatar m-kurtenacker avatar madmann91 avatar mastercassim avatar richardmembarth avatar simoll avatar stlemme avatar tillspeicher avatar timopgros avatar x1cygnu 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

impala's Issues

Ordering problems in IR construction of nested functions

Impala IR generation fails when an inner function (indirectly) depends on code in the body of the enclosing function. Seems like code for the body is generated after the inner functions are.

fn f(b: bool, i: int) -> int {
    fn F() -> ! { r(i-1) }
    fn T() -> ! { r(i) }
    let ret : fn(int) -> ! = return;
    fn r(x: int) -> ! { ret(x) }
    if (b) {
        T()
    } else {
        F()
    }
}

fn main() -> int {
    f(true, 5)
}

Yields the following error:

impala: .../thorin/src/thorin/def.cpp:34: void thorin::Def::set_op(size_t, const thorin::Def*):
  Assertion `def && "setting null pointer"' failed.
zsh: abort (core dumped)  impala --emit-thorin codegen/bind_ret.impala

When moving lines defining fn F and fn T behind fn r this works.

assertion failed trying to specialize function that invokes closure passed as a struct field

Note the @ in call to fac; removing it makes the code compile fine

impala: /home/user/anydsl/thorin/src/thorin/be/llvm/llvm.cpp:988: llvm::Type* thorin::CodeGen::convert(const thorin::Type*): Assertion `ret' failed.
Aborted (core dumped)
type char = u8;
type str = [char];


extern "C" {
    fn atoi(&str) -> int;
    fn print_int(int) -> ();
}


fn subber(a: int, b: int) -> int {
	a - b
}

fn invocator(a:fn(int) -> int, b: int) -> int {
	a(b)
}

fn fac_rec(n : int, d:explicit_delegate)->int {
    if (n <= 0) {
        1
    } else {
        n * fac_rec(d.callable(n), d)
    }
}

struct explicit_delegate {
    callable: fn(int) -> int
}

fn fac_nrec(n : int, delta: int) -> int {
    let subber1 = |x: int| subber(x, delta);
    let ci = explicit_delegate{
        callable : subber1
    };
    @fac_rec(n, ci)
}

fn main(argc: int, argv: &[&str]) -> int {
    let n = if argc >= 2 { atoi(argv(1)) } else { 1 };
    let res = fac_nrec(10, n);
    print_int(res);
    res
}

impala compiler hangs (diverges?) compiling parameterized factorial

Code:
Note there are no specialization annotations (@), adding halt annotations ($) doesnt seem to help either.

fn subber(a: int, b: int) -> int {
	a - b
}

fn fac_rec(n : int, muter: fn(int) -> int) -> int {
    if (n <= 0) {
        1
    } else {
    	let nn = muter(n);
        n * $fac_rec(nn, muter)
    }
}

fn fac_nrec(n : int) -> int {
	let subber1 = |x: int| subber(x, 1);
	fac_rec(n, subber1)
}

fn main() -> int {
	fac_nrec(5)
    //if @fac_rec(5) == 120 { 0 } else { 1 }
}

This same code is trivially runnable in JS console:

(function(){
    var s=(a,b)=>a-b;
    var s1=(a)=>s(a,1);
    function fac_rec(n, muter){
    if(n<=0){ return 1} else {return n*fac_rec(muter(n),muter)}
	}
	console.log(fac_rec(5,s1));
})()

Cannot return tuple type

The following code crashes :

type Blob = (i32, i32);
fn blobify(i: i32) -> Blob {
    (i, i)
}

fn main() -> () {
    let b = blobify(42);
}

Run with -emit-thorin.

Incompatible named structs not rejected by sema

The following code types: impala test.impala

struct S1 {
    a : i32
}
struct S2 {
    a : i32
}

fn get2(a: i32) -> S2 { get1(a) }
fn get1(a: i32) -> S1 { S1 { a : a } }

fn main(i: i32) -> i32 {
    get2(i).a
}

But asserts when generating llvm impala -emit-llvm test.impala:

impala: thorin/src/thorin/util/cast.h:26: L* thorin::scast(R*) [with L = thorin::PrimType; R = thorin::Type]: Assertion `(!r || dynamic_cast<L*>(r)) && "cast not possible"' failed.
Aborted (core dumped)

get2() returns S2, but get1() gives S1. This should be detected by Sema.

Error: : CommandLine Error: Option 'verify-dom-info' registered more than once!

This is not an issue with AnyDSL specifically but rather (I guess) a problem with linking against llvm libs (because of my system setup). I am asking for help in case somebody faced the same problem before.

Today, I had to install some new packages (bumblebee and cuda toolkit) to work on AnyDSL on Linux rather Windows like I used to. During the process, I guess some packages needed to install llvm libs. Running: dnf list installed | grep llvm, produces the following output:

llvm-libs.i686                         3.9.1-2.fc25             @updates        
llvm-libs.x86_64                       3.9.1-2.fc25             @updates

Now (using the standard AnyDSL installation), when I try to build something using impala (e.g. stincilla), I get the following error:

[  2%] Generating gaussian.ll
: CommandLine Error: Option 'verify-dom-info' registered more than once!
LLVM ERROR: inconsistency in registered CommandLine options
CMakeFiles/gaussian.dir/build.make:79: recipe for target 'gaussian.ll' failed

According to this (http://lists.llvm.org/pipermail/lldb-dev/2015-March/006852.html), this might be an issue of linking some llvm libs twice.

Does anyone have any pointers on how to resolve this issue?

Intrinsic for undef values

It would be useful to have a (polymorphic) intrinsic to create bottom values. Something in the lines of:

extern "thorin" {
  fn undef[T]() -> T;
}

Indefinite Array in Struct Fails on Access

When compiling the following code with impala (2ab3ab4)

struct CS {
    sizes : [i32],
    count : i32,
}

fn main() -> i32 {
 let cache_sizes = CS {sizes: [32*1024, 256*1024, 20*1024*1024], count: 3}; // in bytes
 
 for i in range(0, cache_sizes.count) {
     print_int(cache_sizes.sizes(i));
 }
 
 0
}

Impala fails with the following message:

Assertion failed: ((!r || dynamic_cast<L*>(r)) && "cast not possible"), function scast, file dev/anydsl/thorin/src/thorin/util/cast.h, line 26.
Abort trap: 6

I don't see the cast here and the same code works if sizes and count are not in a struct but two local variables.

Compilation aborts when the member function of a mutable struct is called inside a higher-order function

For the following code the compilation aborts without error message:

type real = f64;
type size_t = u64;

struct vector{
    n: size_t,
    buf: fn()->Buffer,
    set: fn(size_t, real) -> (),
    get: fn(size_t) -> real
}

fn get_vector(n: size_t)->vector{
    let tmp : Buffer = alloc_cpu(n as i32 * sizeof[real]());
    vector{
        n: n,
        buf: ||{tmp},
        set: |i,v|{bitcast[&mut[real]](tmp.data)(i) = v},
        get: |i| {bitcast[&[real]](tmp.data)(i)}
    }
}

fn loop(lower: size_t, upper: size_t, body: fn(size_t) -> ()) -> () {
    if lower < upper {
        body(lower);
        loop(lower+(1 as size_t), upper, body, return)
    }
}

fn main ()->(){
    let mut v = get_vector(10 as size_t);
    for i in loop (1 as size_t, 10 as size_t ) {
        v.set(i, 42.0);
    }
}

The problem only occurs if the variable "v" is declared mutable.
Impala flags: -emit-llvm -O3 -log-level error
impala commit 16c3ff7
thorin commit 72e23ec

Parsing of constants under windows

Hexadecimal constants may result in wrong values under windows (e.g. 0x80000000 results in 2147483647). This is because the parser relies on the standard library function strtol, which returns LONG_MAX in case the number is not representable in 32 bits. In this case 0x80000000 is treated as a positive constant, which explains the returned value.

We have two options:

  • treat the constant 0x80000000 as a positive number, and emit a warning when an overflow occurs,
  • do as in C and treat the hexadecimal representation of the number as its binary representation - hence signless.

lvalue: Inference rules for field expressions

In the lvalue branch, the type inference rules are broken for field expressions:

const Type* FieldExpr::check(InferSema& sema) const {
    auto ltype = sema.check(lhs());
    if (is_ptr(ltype)) {
        PrefixExpr::create_deref(lhs_.get());
        ltype = sema.check(lhs());
    }

    auto ref = split_ref_type(ltype);

    if (auto struct_type = ltype->isa<StructType>()) {
        if (auto field_decl = struct_type->struct_decl()->field_decl(symbol())) {
            if (ref)
                Ref2ValueExpr::create(lhs())->type();
            return sema.wrap_ref(ref, struct_type->op(field_decl->index()));
        }
    }

    return sema.wrap_ref(ref, ltype->is_known() ? sema.type_error() : sema.find_type(this));
}

Assuming that the structure type is known, but the field type is not, we will return a type such as reference to ?23 in the first type inference iteration. In the next iteration, we will have inserted a Ref2Value node, which means that lhs will now have a non-reference type. Hence, this iteration will return a non-reference type as well, which cannot be unified with the type coming from the previous iteration.

This is an example that triggers the bug:

fn iterate_rays(rays: &Ray) -> () {
    rays.org;
}

struct Ray {
    org: Vec4
}

struct Vec4 {
    w: f32
}

My suggestion to fix this issue: Do not create Ref2Value nodes here, as it makes little sense from a type checking perspective (you need a reference to a structure to get a reference to a structure field). This Ref2Value should be located at the usage site, when necessary.

Compiler segfaults for recursive functions

The Impala compiler segfaults on the following minmal example:

struct node {
    value : value_t,
    left  : &node,
    right : &node
}

fn post_order_visit(n: &node, visit: fn(value_t) -> ()) -> () {
    if(n.left != 0 as &node)  { post_order_visit(n.left, visit);  }
    if(n.right != 0 as &node) { post_order_visit(n.right, visit); }
    visit(n.value);
}

extern
fn tree_sum(levels: int) -> value_t {
    let tree = ~node{value: 0 as value_t, left: 0 as &node, right: 0 as &node }; 
    let mut sum = 0 as value_t;
    post_order_visit(tree, |x| { sum += x; } );
    sum
}

This one will also fail:

struct node {
    value : value_t,
    left  : &node,
    right : &node
}

fn make_tree(gen: fn() -> value_t, levels: int) -> &node {
    if(levels < 1) { return (0 as &node) }
    ~node { value: gen(),
            left:  make_tree(gen, levels-1), 
            right: make_tree(gen, levels-1)
    }
}

extern
fn tree_sum(levels: int) -> value_t {    
    let tree = make_tree(||{0 as value_t}, levels);
   0 as value_t;
}

Note that removing the recursive calls will fix it.

Fixed size arrays broken with -O3

The following code leads to correct results with -O2 but wrong with -O3

fn main() -> () {
    let N = 4;
    let mut A = [N:i32];
    let mut B = ~[N:i32];
    let mut C = [0, 0, 0, 0];
    let mut D = [N:i32];
    
    for i in $range(0, N) {
        A(i) = i*i;
        B(i) = i*i;
        C(i) = i*i;
    }
    
    D(0) = 0;
    D(1) = 1;
    D(2) = 4;
    D(3) = 9;
    // D(4) = 16; // should break, but doesn't
    
    print_string("A: "); print_array(bitcast[&[i32]](&A), N); print_string("\n");
    print_string("B: "); print_array(bitcast[&[i32]]( B), N); print_string("\n");
    print_string("C: "); print_array(bitcast[&[i32]](&C), N); print_string("\n");
    print_string("D: "); print_array(bitcast[&[i32]](&D), N); print_string("\n");
}

fn print_array(arr: &[i32], num: i32) -> () {
    print_string("["); print_int(arr(0));
    for i in $range(1, num) {
        print_string(", "); print_int(arr(i));
    }
    print_string("]");
}

Output with -O3:

A: [0, 0, 0, 0]
B: [0, 1, 4, 9]
C: [0, 1, 4, 9]
D: [0, 0, 0, 0]

Revealing module design pattern implementation causes Segmentation Fault

I'm trying to implement something like the revealing module pattern in my anyDSL application. Unfortunately my implementation causes a segmentation fault

I have prepared a minimal example:

min.cpp:

#include <stdio.h>
#include "min.h" // generated by anyDSL

int main(int arc, char** argv) {
    run_adsl();
    return 0;
}

min.impala:

extern "C" {
    fn printf( &[u8], int ) -> ();
}

extern fn run_adsl() -> () {
    let module = myModule();
    printf("A) number = %i \n", module.number);
    module.increaseNumber(); // If this line is removed the code runs correctly
}

struct Module {
	number:         int,
	increaseNumber: fn() -> ()
}

fn myModule( ) -> ( Module ) {

	let mut module = Module {
		number:  0,
		increaseNumber: | | -> (){ }
	};

	module.increaseNumber = | | -> (){
		module.number++;
	};
}

Compilation commands:

impala min.impala -emit-llvm -emit-c-interface
llvm-as min.ll
clang min.cpp min.bc -o min.x

In the minimal example, I create a module structure which contains a pointer to a function. In the actual implementation of the code, the myModule function would return different versions of the module struct with pointers to different functions depending on the inputs passed.

The above code when ran produces the following output:

pupoSDC@xxxx:~/Desktop$ ./hello.x 
A) number = 0 
A) number = 0 
Segmentation fault (core dumped)

Any ideas if I'm doing something wrong, or something that is not supported by the language?

How to convert a double address to a double array adress?

Short Version

Is there any way to convert a reference of type double to a reference of
an array of doubles?

&mut double -> &mut [double]

Long Version

I have a function with the following (simplified) signature:

fn demo( input: &mut [double] ) -> () {
    // Irrelevant to the topic
}

I'd like to be able to call this method passing a reference to a cell in an array
which may not be 0. For example, in this minimalist example i want to call
the demo function for the array at entry 3.

fn main( array: &mut [double] ){
   demo( &mut array(3), 2  )
}

The above code throws the following error:

error: mismatched types: expected '&mut <infer error: [f64], f64>' but found '&mut f64' as argument type

Please ignore all the memory and segfault risks of this demo code. They were
considered in the full version of the code. Also, I'd like to avoid an approach
where a reference to the array and an integer for the entry are passed to the
demo function. Eg.:

fn demo( input: &mut [double], entry: uint ) -> () {
    // Not what i'm looking for.
}

fn main( array: &mut [double] ){
   demo( array, 3  )
}

Thank you for your help

SimdType is an ArrayType

This has the implication that we can implicitly cast [4 x int] to simd[4 x int].
We could either change the subclass relation in the C++ implementation or fix is_subtype.

Upgrade to CMake 3.1

Use either target_compile_features() or CXX_STANDARD and CXX_STANDARD_REQUIRED to select the C++ standard.

match negative numbers

Matching a negative number is currently not supported:

fn test(id: i32) -> i32 {
    match id {
        23 => 42,
        -1 => 47,
        _  => 11
    }
}
impala test.impala
test.impala:4 col 9: error: expected identifier, got '-' while parsing path
test.impala:4 col 9: error: expected '=>', got '-' while parsing pattern of match expression

Incorrect code accepted

The following code should not be accepted:

fn main(i : int) -> int {
    (|i| i) (1, 2)
}

But Impala accepts it happily (and then breaks during code generation).

regressions with new unit value

There are a number of regressions with the new handling of unit values:

- REQUIRED test failed: codegen/break.impala
- REQUIRED test failed: codegen/continue.impala
- REQUIRED test failed: codegen/fib.impala
- REQUIRED test failed: codegen/fieldexpr.impala
- REQUIRED test failed: codegen/fold.impala
- REQUIRED test failed: codegen/labeled_break.impala
- REQUIRED test failed: codegen/primes_for.impala
- REQUIRED test failed: codegen/range_f.impala
- REQUIRED test failed: codegen/range_l.impala
- REQUIRED test failed: codegen/void_tailcall.impala
- REQUIRED test failed: codegen/zip.impala
- REQUIRED test failed: codegen/benchmarks/aobench.impala
- REQUIRED test failed: codegen/benchmarks/meteor.impala

These are related to calling continuations.

fieldexpr.impala is an older regression, btw.

Constant expression for smallest i32 emits undef

The following code:

extern "C" {
    fn print_int(i32) -> ();
}

fn main() -> i32 {
    let test : i32 = 1 << 31;
    print_int(test);

    0
}

emits test value as undef while it should be the smallest i32 value.

Parsing of float literals with leading decimal point returns wrong numbers

I noticed a rather strange behavior of my code when using floating point literals with leading decimal points (like .5 for 0.5). The parser does not complain about the missing number in front of the decimal point, so I assumed that I could just omit any leading zero (like in many other languages). However, the actual number being parsed from .5 is actually 5.0 rather than 0.5. This looks like the decimal point is just used for type checking here but ignored when parsing the number.

Example code:

print_string(".5 == 0.5 ? ");
if .5 == 0.5 {
	print_string("true\n");
} else {
	print_string("false\n");
}

print_string(".5 == 5.0 ? ");
if .5 == 5.0 {
	print_string("true\n");
} else {
	print_string("false\n");
}

Output:

.5 == 0.5 ? false
.5 == 5.0 ? true

Compilation problem on while true

Hi,

the following code does not compile for me, except if i change the condition of the while loop to something that is not 'true'. I am using the master branch version.

Code:

fn circular_iteration(sizeLog2 : u64, mut idx : u64, body: fn(u64, fn())) -> () {
    let mask = (1u64 << sizeLog2) - 1u64;
    while true { // this true is triggering the problem
        body(idx);
        idx = (idx + 1u64) & mask;
    }
}

fn main() -> bool {
    for i in circular_iteration(8u64, 42u64) {
        if i == 23u64 {
            break()
        }
        thorin_print_long(i as i64);
        thorin_print_string("\n");
    }
    true
}

Error Message:

impala: /home/srichter/anydsl/anydsl/thorin/src/thorin/analyses/scope.cpp:210: void thorin::Scope::build_rev_rpo(thorin::Array<thorin::Lambda*>): Assertion `n == 0' failed.

Type inference bug

The following example should be rejected by the type system:

enum Direction { Left, Right };

fn get_direction(dir: i32, body: fn(Direction) -> ()) -> () {
    if dir == 0 {
        body(Direction::Left)
    } else {
        (|a| body(a)) (1)
    }
}

However, it passes and fails only in the verify phase later on:

Assertion 'c == a' failed in /space/membarth/projects/anydsl/thorin/src/thorin/continuation.h:171 continuation 'lambda_25' calls 'body_9' of type 'fn(mem, Direction, fn(mem))' but call has type 'fn(mem, qs32, fn(mem))'

Fixing type inference tests

Many tests for impala are broken because we currently print types such as fn(i32) -> i32 as fn(i32, fn(i32)). The code that did the pretty printing previously is now commented out in src/impala/sema/type.cpp. Should we change the tests and get a rid of the commented code, or should we re-enable the pretty printing ?

Type inference of anonymous functions

The following piece of code generates a type checking error, even though it should be accepted:

fn main() -> i32 {
    let id = |x| x;
    id(1i32) + id(1i32)
}

Polymorphic functions broken

The following code generates an assertion at /impala/src/impala/sema/unifiable.h, Line 529:

fn f1[T](input: T) -> () {}
fn f2[T](input: T) -> () {}

Partial Evaluation is being performed unexpectedly

Hi,
For the unroll.impala test, if I add a version of range() after a call to @ range it is still doing partial evaluation. Is this expected?

let unroll = 10;
for i in @range(0, unroll) {
    arr(0) = foo(i);
}
for i in range(0, unroll) { // Is being evaluated
    arr(0) = foo(i);
}

different error messages for same incorrect code

Depending on the order of function declarations, impala emits correct error messages or segfaults.

Correct error message:

fn a(a: i32) -> () { }
fn b() -> () { }
fn main() -> () {
    a(b)
}
test.impala:4 col 7 - 8: error: mismatched types: expected 'i32' but found 'fn(fn())' as argument type

Segfault:

fn a(a: i32) -> () { }
fn main() -> () {
    a(b)
}
fn b() -> () { }
Assertion failed: ((!r || dynamic_cast<L*>(r)) && "cast not possible"), function scast, file thorin/src/thorin/util/cast.h, line 26.
Abort trap: 6

In both cases, the error message should be returned.

For loops with incorrect number of bindings

The following code should not be accepted by Impala :

extern "C" {
    fn plausible_number() -> i32;
    fn print_number(i32) -> ();
}

fn this_function(a: i32, b: i32, c: fn (i32, i32) -> ()) -> () {
    c(a + b, plausible_number());
}

extern fn lolz(k: i32) -> () {
    for i in this_function(0, k) { // Should not be accepted : 'c' takes 2 parameters in function 'broken'
       print_number(i)
    }
}

simple function which should specialise causes data to be copied on stack

Hello,
I'm sorry if this is not an impala issue. I have the following code:

struct Data {
    item: i32,
}

extern fn foo(arr: &[Data], i: i32) -> () {
    let f = @ |i| arr(i);
    cpu_prefetch(&f(i) as &u8, 0, 3, 1)
}

extern fn bar(arr: &[Data], i: i32) -> () {
    cpu_prefetch(&arr(i) as &u8, 0, 3, 1)
}

Which yields the following result (latest commits on mem2reg branch of impala and thorin):

0000000000001130 <foo>:
    1130:     movslq %esi,%rax
    1133:     mov    (%rdi,%rax,4),%eax
    1136:     mov    %eax,-0x8(%rsp)
    113a:     prefetcht0 -0x8(%rsp)
    113f:     retq

0000000000001140 <bar>:
    1140:     movslq %esi,%rax
    1143:     prefetcht0 (%rdi,%rax,4)
    1147:     retq
    1148:     nopl   0x0(%rax,%rax,1)

I would expect f to inline and the code for both functions to be the same. Instead, data gets copied on the stack before the prefetch, which makes the latter useless.

[eurollvm branch] assertion failed compiling generic function call from recursive function

I improved the example from #58 a bit more :)

fn subber(a: int, b: int) -> int {
	a - b
}

fn invocator[T, TR](a:fn(T) -> TR, b: T) -> TR {
	a(b)
}

fn fac_rec(n : int, muter: fn(int) -> int) -> int {
	let swrap = |x: int| invocator(muter,x);
    if (n <= 0) {
        1
    } else {
    	let nn = swrap(n);
        n * fac_rec(nn, swrap)
    }
}

fn fac_nrec(n : int) -> int {
	let subber1 = |x: int| subber(x, 1);
	@fac_rec(n, subber1)
}

fn main() -> int {
	fac_nrec(5)
    //if @fac_rec(5) == 120 { 0 } else { 1 }
}

and this gets me this assertion:

user@linux-thorin:~/anydsl/impala/test$ impala --emit-llvm -O3 codegen/fac_rec.impala
impala: /home/user/anydsl/impala/src/impala/emit.cpp:539: virtual const thorin::Def* impala::TypeAppExpr::remit(impala::CodeGen&) const: Assertion `false && "TODO"' failed.
Aborted (core dumped)

... and i'm not really sure whether this is a bug or i'm trying to compile something strange :)

UPD: specifying concrete types gets rid of assertion, i'm impressed.

[eurollvm] divergence while compiling factorial with recursive record

This one never finishes too ;)
Object encoding via recursive record as in [Cardelli 1984]

type char = u8;
type str = [char];


extern "C" {
    fn atoi(&str) -> int;
    fn print_int(int) -> ();
}

struct MyInt { 
    get: fn() -> int,
    set: fn(int) -> MyInt,
    bump: fn() -> MyInt
}

fn makeInt(a: int) -> MyInt {
   MyInt {
        get: || a,
        set: |a2| makeInt(a2),
        bump: || makeInt(a-1)
   }
}

fn fac_oo(n : MyInt)->MyInt {
    if (n.get() <= 0) {
        makeInt(1)
    } else {
        let dec = n.bump();
        makeInt(n.get() * fac_oo(dec).get())
    }
}

fn fac_wrap(n : int) -> int {
    fac_oo(makeInt(n)).get()
}

fn main(argc: int, argv: &[&str]) -> int {
    let n = if argc >= 2 { atoi(argv(1)) } else { 6 };

    let res = fac_wrap(n);

    print_int(res);
    res 
}

Wrong ordering of memory objects for conditionals that may have side effects

Impala segfaults on windows for the following code:

fn @scalar(f: f32) -> f32 { f }

fn main() -> i32 {
    let mut value = 1.f;
    if 1.f < scalar(0.01f) || 0.2f < scalar(0.01f) || 0.3f < scalar(0.01f) {
        value = 0.7f;
    }
    if value == 1.0f { 0 } else { 1 }
}

Generated thorin code:

main_10(mem mem_11, fn(mem, qs32) return_12) extern  @(bool 0, bool 0)
    (mem, frame) _20 = enter mem_11
    mem _21 = extract _20, qu32 0
    frame _22 = extract _20, qu32 1
    pf32* value_24 = slot _22
    mem value_25 = store _21, value_24, pf32 1
    scalar_6(value_25, pf32 0.01, scalar_cont_42)

    scalar_cont_42(mem mem_43, pf32 scalar_44)
        bool _45 = lt pf32 1, scalar_44
        br_1(_45, or_lhs_t_36, or_lhs_f_37)

    or_lhs_f_37()
        scalar_6(mem_43, pf32 0.01, scalar_cont_47)

    scalar_cont_47(mem mem_48, pf32 scalar_49)
        bool _50 = lt pf32 0.2, scalar_49
        or_result_38(mem_48, _50)

    or_lhs_t_36()
        or_result_38(mem_48, bool 1)

    or_result_38(mem mem_39, bool or_result_40)
        br_1(or_result_40, or_lhs_t_31, or_lhs_f_32)

    or_lhs_f_32()
        scalar_6(mem_39, pf32 0.01, scalar_cont_52)

    scalar_cont_52(mem mem_53, pf32 scalar_54)
        bool _55 = lt pf32 0.3, scalar_54
        or_result_33(mem_53, _55)

    or_lhs_t_31()
        or_result_33(mem_53, bool 1)

    or_result_33(mem mem_34, bool or_result_35)
        br_1(or_result_35, if_then_26, if_else_27)

    if_else_27()
        if_join_28(mem_34, tuple ())

    if_then_26()
        mem _57 = store mem_34, value_24, pf32 0.7
        if_join_28(_57, tuple ())

    if_join_28(mem mem_29, () if_join_30)
        (mem, pf32) _64 = load mem_29, value_24
        mem _65 = extract _64, qu32 0
        pf32 _66 = extract _64, qu32 1
        bool _67 = eq _66, pf32 1
        br_1(_67, if_then_59, if_else_60)

    if_else_60()
        if_join_61(_65, qs32 1)

    if_then_59()
        if_join_61(_65, qs32 0)

    if_join_61(mem mem_62, qs32 if_join_63)
        return_12(mem_62, if_join_63)


br_1(bool br_2, fn() br_3, fn() br_4)



scalar_6(mem mem_7, pf32 f_8, fn(mem, pf32) return_9) @(bool 1, bool 1, bool 1)
    (mem, frame) _13 = enter mem_7
    mem _15 = extract _13, qu32 0
    return_9(_15, f_8)

Bitwise negation needed

There is currently no negation operator in impala. It should be included since it is useful for masks and bit-wise arithmetic (bit shifts are already implemented). The negation sign in C is the tilde ~. We cannot use it here because it is used by owned pointers. What symbol should we use ?

Re-interpreting a value of a large type as an array of a smaller type

I want to re-interpret a value as an array of values of a smaller type. For example, an i32 as an array of 4 i8s. Also, the source (big) and target (small) types are polymorphic so the size of the target array is not fixed (in terms of the number of elements rather than the total size in bytes). Can I do that?

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.