def test_llvm_eval2():
    e = LLVMEvaluator()
    e.add_module("""\
@count = global i64 0

define i64 @f1()
{
    store i64 4, i64* @count
    %1 = load i64, i64* @count
    ret i64 %1
}
""")
    assert e.intfn("f1") == 4

    e.add_module("""\
@count = external global i64

define i64 @f2()
{
    %1 = load i64, i64* @count
    ret i64 %1
}
""")
    assert e.intfn("f2") == 4

    with pytest.raises(RuntimeError):
        e.add_module("""\
define i64 @f3()
{
    ; FAIL: @count is not defined
    %1 = load i64, i64* @count
    ret i64 %1
}
""")
def test_llvm_callback_stub():
    from ctypes import c_int, c_void_p, CFUNCTYPE, cast
    from lfortran.codegen.gen import create_callback_stub
    from llvmlite import ir
    data = [0, 0]
    ftype = CFUNCTYPE(c_int, c_int, c_int)

    @ftype
    def f(a, b):
        data[0] = a
        data[1] = b
        return a + b

    faddr = cast(f, c_void_p).value
    mod = ir.Module()
    create_callback_stub(
        mod, "f", faddr,
        ir.FunctionType(ir.IntType(64),
                        [ir.IntType(64), ir.IntType(64)]))
    e = LLVMEvaluator()
    e.add_module(str(mod))
    stub = ftype(e.ee.get_function_address('f'))
    assert data == [0, 0]
    assert stub(2, 3) == 5
    assert data == [2, 3]
def test_llvm_callback0():
    from ctypes import c_int, c_void_p, CFUNCTYPE, cast
    data = [0, 0]
    ftype = CFUNCTYPE(c_int, c_int, c_int)

    @ftype
    def f(a, b):
        data[0] = a
        data[1] = b
        return a + b

    faddr = cast(f, c_void_p).value
    e = LLVMEvaluator()
    e.add_module("""\
define i64 @addrcaller(i64 %a, i64 %b)
{
    %f = inttoptr i64 %ADDR to i64 (i64, i64)*
    %r = call i64 %f(i64 %a, i64 %b)
    ret i64 %r
}
""".replace("%ADDR", str(faddr)))
    addrcaller = ftype(e.ee.get_function_address('addrcaller'))
    assert data == [0, 0]
    assert addrcaller(2, 3) == 5
    assert data == [2, 3]
def test_llvm_eval1_fail():
    e = LLVMEvaluator()
    with pytest.raises(RuntimeError):
        e.add_module("""\
define i64 @f1()
{
    ; FAIL: "=x" is incorrect syntax
    %1 =x alloca i64
}
""")
def test_llvm_array2():
    """
    This test represents the array as a structure that contains the array
    size and data.
    """
    e = LLVMEvaluator()
    e.add_module("""\

%array = type {i64, [3 x i64]}

; Sum the three elements in %a
define i64 @sum3(%array* %a)
{
    %a1addr = getelementptr %array, %array* %a, i64 0, i32 1, i64 0
    %a1 = load i64, i64* %a1addr

    %a2addr = getelementptr %array, %array* %a, i64 0, i32 1, i64 1
    %a2 = load i64, i64* %a2addr

    %a3addr = getelementptr %array, %array* %a, i64 0, i32 1, i64 2
    %a3 = load i64, i64* %a3addr

    %tmp = add i64 %a2, %a1
    %r = add i64 %a3, %tmp

    ret i64 %r
}


define i64 @f()
{
    %a = alloca %array

    %idx0 = getelementptr %array, %array* %a, i64 0, i32 0
    store i64 3, i64* %idx0

    %idx1 = getelementptr %array, %array* %a, i64 0, i32 1, i64 0
    store i64 1, i64* %idx1
    %idx2 = getelementptr %array, %array* %a, i64 0, i32 1, i64 1
    store i64 2, i64* %idx2
    %idx3 = getelementptr %array, %array* %a, i64 0, i32 1, i64 2
    store i64 3, i64* %idx3

    %r = call i64 @sum3(%array* %a)
    ret i64 %r
}
""")
    assert e.intfn("f") == 6
def test_llvm_callback_py2():
    from lfortran.codegen.gen import create_callback_py
    from llvmlite import ir
    data = [0, 0]

    def g(a, b):
        data[0] = a
        data[1] = b
        return a + b

    mod = ir.Module()
    ftype = create_callback_py(mod, g)
    e = LLVMEvaluator()
    e.add_module(str(mod))
    stub = ftype(e.ee.get_function_address('g'))
    assert data == [0, 0]
    assert stub(2, 3) == 5
    assert data == [2, 3]
def test_llvm_array1():
    """
    This test represents the array directly as a pointer.
    """
    e = LLVMEvaluator()
    e.add_module("""\
; Sum the three elements in %a
define i64 @sum3(i64* %a)
{
    %a1addr = getelementptr i64, i64* %a, i64 0
    %a1 = load i64, i64* %a1addr

    %a2addr = getelementptr i64, i64* %a, i64 1
    %a2 = load i64, i64* %a2addr

    %a3addr = getelementptr i64, i64* %a, i64 2
    %a3 = load i64, i64* %a3addr

    %tmp = add i64 %a2, %a1
    %r = add i64 %a3, %tmp

    ret i64 %r
}


define i64 @f()
{
    %a = alloca [3 x i64]

    %a1 = getelementptr [3 x i64], [3 x i64]* %a, i64 0, i64 0
    store i64 1, i64* %a1

    %a2 = getelementptr [3 x i64], [3 x i64]* %a, i64 0, i64 1
    store i64 2, i64* %a2

    %a3 = getelementptr [3 x i64], [3 x i64]* %a, i64 0, i64 2
    store i64 3, i64* %a3

    %r = call i64 @sum3(i64* %a1)
    ret i64 %r
}
""")
    assert e.intfn("f") == 6
def test_llvm_callback_py3():
    from lfortran.codegen.gen import create_callback_py
    from llvmlite import ir
    data = [0, 0, 0]

    def f(a, b, c):
        data[0] = a
        data[1] = b
        data[2] = c
        return a + b + c

    mod = ir.Module()
    ftype = create_callback_py(mod, f, "h")
    e = LLVMEvaluator()
    e.add_module(str(mod))
    stub = ftype(e.ee.get_function_address('h'))
    assert data == [0, 0, 0]
    assert stub(2, 3, 5) == 10
    assert data == [2, 3, 5]
def test_llvm_callback_py0():
    from lfortran.codegen.gen import create_callback_py
    from llvmlite import ir
    data = [0]

    def f():
        return data[0]

    mod = ir.Module()
    ftype = create_callback_py(mod, f)
    e = LLVMEvaluator()
    e.add_module(str(mod))
    stub = ftype(e.ee.get_function_address('f'))
    assert data == [0]
    assert stub() == 0
    data[0] = 2
    assert stub() == 2
    data[0] = 5
    assert stub() == 5
Exemple #10
0
def test_function1():
    source = """\
integer function fn1(a, b) result(r)
integer, intent(in) :: a, b
r = a + b
end function
"""
    ast = src_to_ast(source, translation_unit=False)
    asrepr = ast_to_asr(ast)
    verify_asr(asrepr)

    assert 'fn1' in asrepr.global_scope.symbols
    fn1 = asrepr.global_scope.symbols['fn1']
    assert fn1.args[0].name == "a"
    assert fn1.args[1].name == "b"
    assert fn1.return_var.name == "r"
    assert fn1.body[0].target == fn1.return_var
    assert fn1.body[0].value.left == fn1.args[0]
    assert fn1.body[0].value.right == fn1.args[1]

    llmod = asr_to_llvm(asrepr)
    e = LLVMEvaluator()
    e.add_module(str(llmod))
    e.add_module("""\
declare i64 @fn1(i64* %".1", i64* %".2")

define i64 @f1()
{
    %a = alloca i64
    %b = alloca i64
    store i64 2, i64* %a
    store i64 3, i64* %b
    %r = call i64 @fn1(i64* %a, i64* %b)
    ret i64 %r
}
""")
    assert e.intfn("f1") == 5
def test_llvm_eval3():
    e = LLVMEvaluator()
    e.add_module("""\
@count = global i64 5
""")

    e.add_module("""\
@count = external global i64

define i64 @f1()
{
    %1 = load i64, i64* @count
    ret i64 %1
}

define void @inc()
{
    %1 = load i64, i64* @count
    %2 = add i64 %1, 1
    store i64 %2, i64* @count
    ret void
}
""")
    assert e.intfn("f1") == 5
    e.voidfn("inc")
    assert e.intfn("f1") == 6
    e.voidfn("inc")
    assert e.intfn("f1") == 7

    e.add_module("""\
@count = external global i64

define void @inc2()
{
    %1 = load i64, i64* @count
    %2 = add i64 %1, 2
    store i64 %2, i64* @count
    ret void
}
""")
    assert e.intfn("f1") == 7
    e.voidfn("inc2")
    assert e.intfn("f1") == 9
    e.voidfn("inc")
    assert e.intfn("f1") == 10
    e.voidfn("inc2")
    assert e.intfn("f1") == 12

    # Test that we can have another independent LLVMEvaluator and use both at
    # the same time:
    e2 = LLVMEvaluator()
    e2.add_module("""\
@count = global i64 5

define i64 @f1()
{
    %1 = load i64, i64* @count
    ret i64 %1
}

define void @inc()
{
    %1 = load i64, i64* @count
    %2 = add i64 %1, 1
    store i64 %2, i64* @count
    ret void
}
""")
    assert e2.intfn("f1") == 5
    e2.voidfn("inc")
    assert e2.intfn("f1") == 6
    e2.voidfn("inc")
    assert e2.intfn("f1") == 7

    assert e.intfn("f1") == 12
    e2.voidfn("inc")
    assert e2.intfn("f1") == 8
    assert e.intfn("f1") == 12
    e.voidfn("inc")
    assert e2.intfn("f1") == 8
    assert e.intfn("f1") == 13
def test_llvm_eval1():
    e = LLVMEvaluator()
    e.add_module("""\
define i64 @f1()
{
    ret i64 4
}
""")
    assert e.intfn("f1") == 4
    e.add_module("")
    assert e.intfn("f1") == 4

    e.add_module("""\
define i64 @f1()
{
    ret i64 5
}
""")
    assert e.intfn("f1") == 5
    e.add_module("")
    assert e.intfn("f1") == 5
def test_llvm_eval4():
    e = LLVMEvaluator()
    e.add_module("""\
@count = global i64 5

define i64 @f1()
{
    %1 = load i64, i64* @count
    ret i64 %1
}

define void @inc()
{
    %1 = load i64, i64* @count
    %2 = add i64 %1, 1
    store i64 %2, i64* @count
    ret void
}
""")
    assert e.intfn("f1") == 5
    e.voidfn("inc")
    assert e.intfn("f1") == 6
    e.voidfn("inc")
    assert e.intfn("f1") == 7

    e.add_module("""\
declare void @inc()

define void @inc2()
{
    call void @inc()
    call void @inc()
    ret void
}
""")
    assert e.intfn("f1") == 7
    e.voidfn("inc2")
    assert e.intfn("f1") == 9
    e.voidfn("inc")
    assert e.intfn("f1") == 10
    e.voidfn("inc2")
    assert e.intfn("f1") == 12

    with pytest.raises(RuntimeError):
        e.add_module("""\
define void @inc2()
{
    ; FAIL: @inc is not defined
    call void @inc()
    call void @inc()
    ret void
}
""")