Skip to content

@ccallable: Emit a header file with given name #1861

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 28, 2023

Conversation

Smit-create
Copy link
Collaborator

@Smit-create Smit-create commented May 26, 2023

Fixes #1797

@Smit-create Smit-create requested a review from certik May 26, 2023 07:09
@certik
Copy link
Contributor

certik commented May 26, 2023

Let's add a test for this?

@Smit-create Smit-create requested a review from certik May 28, 2023 03:34
@Smit-create Smit-create marked this pull request as ready for review May 28, 2023 03:46
Copy link
Contributor

@certik certik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks great.

We should add a test that calls this from C and includes the header file, to ensure that everything actually works. We can do that in a next PR.

@certik certik merged commit 9e8b2db into lcompilers:main May 28, 2023
@Smit-create Smit-create deleted the i-1797 branch May 28, 2023 04:05
@Smit-create
Copy link
Collaborator Author

Thanks @certik. The test is added and it works.

Comment on lines +46 to +51
@ccallable(header="_test_bindc_03_my_header.h")
def test_emit_header_ccallable() -> i32:
i: i32 = 5
assert i == 5
i = i*5
return i + 10
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See this test. The header file will be created and will be used in the original file.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, the generated file contains the header file?

I think we still need a handwritten file that includes it, to be sure that all the arguments are compatible.

Copy link
Collaborator Author

@Smit-create Smit-create May 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

% lpython --show-c integration_tests/bindc_03.py > b.c
Will generate two file.

  1. main file:
#include <complex.h>
#include <inttypes.h>
#include "_test_bindc_03_my_header.h"
#include "bindc_03b.h"

#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <lfortran_intrinsics.h>


struct dimension_descriptor
{
    int32_t lower_bound, length;
};
struct ArrayWrapped {
 void* array;
};


struct i32
{
    int32_t *data;
    struct dimension_descriptor dims[32];
    int32_t n_dims;
    bool is_allocated;
};


inline void struct_deepcopy_ArrayWrapped(struct ArrayWrapped* src, struct ArrayWrapped* dest);


// Implementations
int32_t __lpython_overloaded_4___lpython_floordiv(int32_t a, int32_t b)
{
    int32_t _lpython_return_variable;
    double r;
    int32_t result;
    r = (double)(a)/(double)(b);
    result = (int32_t)(r);
    if (r >=   0.00000000000000000e+00 || (double)(result) == r) {
        _lpython_return_variable = result;
        return _lpython_return_variable;
    }
    _lpython_return_variable = result - 1;
    return _lpython_return_variable;
}

int32_t __lpython_overloaded_2___mod(int32_t a, int32_t b)
{
    int32_t _lpython_return_variable;
    _lpython_return_variable = a - __lpython_overloaded_4___lpython_floordiv(a, b)*b;
    return _lpython_return_variable;
}

float _lfortran_caimag(float complex x);

double _lfortran_zaimag(double complex x);

void gpy(void* a, int32_t value, bool offset_value)
{
    g(a, value, offset_value);
}

void f(void* q_void)
{
    int32_t el;
    int32_t i;
    struct i32 q_value;
    struct i32* q = &q_value;
    q->n_dims = 1;
    q->dims[0].lower_bound = 0;
    q->dims[0].length = 0;
    q->data = (int32_t*) q_void;
    for (i=0; i<=10 - 1; i++) {
        {
            void* q2;
            q2 = (void*) &q->data[(i - q->dims[0].lower_bound)];
            gpy(q2, i*i, (bool)(__lpython_overloaded_2___mod(i, 2)));
            el = q->data[(i - q->dims[0].lower_bound)];
            printf("%d\n", el);
            ASSERT(el == i*i + __lpython_overloaded_2___mod(i, 2));
        }
    }
}

void h(void* q_void)
{
    int32_t el;
    int32_t i;
    struct i32 q_value;
    struct i32* q = &q_value;
    q->n_dims = 1;
    q->dims[0].lower_bound = 0;
    q->dims[0].length = 0;
    q->data = (int32_t*) q_void;
    for (i=0; i<=10 - 1; i++) {
        {
            el = q->data[(i - q->dims[0].lower_bound)];
            printf("%d\n", el);
            ASSERT(el == i*i + __lpython_overloaded_2___mod(i, 2));
        }
    }
}

void run()
{
    void* a;
    struct ArrayWrapped array_wrapped_value;
    struct ArrayWrapped* array_wrapped = &array_wrapped_value;
    struct ArrayWrapped array_wrapped1_value;
    struct ArrayWrapped* array_wrapped1 = &array_wrapped1_value;
    uint64_t q;
    int32_t size;
    void* x;
    array_wrapped->array = a;
    size = 10;
    a = get_array(size);
    ASSERT(a != NULL);
    array_wrapped->array = a;
    f(array_wrapped->array);
    q = (uint64_t)(a);
    x = (void*)(q);
    array_wrapped->array = x;
    f(array_wrapped->array);
    struct_deepcopy_ArrayWrapped(array_wrapped, array_wrapped1);
    h(array_wrapped1->array);
    ASSERT(test_emit_header_ccallable() == 35);
}

void _lpython_main_program()
{
    run();
}

int main(int argc, char* argv[])
{
    _lpython_set_argv(argc, argv);
    _lpython_main_program();
    return 0;
}

void struct_deepcopy_ArrayWrapped(struct ArrayWrapped* src, struct ArrayWrapped* dest) {
    dest->array =  src->array;
}
  1. header file:
#ifndef _TEST_BINDC_03_MY_HEADER_H
#define _TEST_BINDC_03_MY_HEADER_H

#include <complex.h>
#include <inttypes.h>

#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <lfortran_intrinsics.h>


int32_t test_emit_header_ccallable()
{
    int32_t _lpython_return_variable;
    int32_t i;
    i = 5;
    ASSERT(i == 5);
    i = i*5;
    _lpython_return_variable = i + 10;
    return _lpython_return_variable;
}



#endif

Copy link
Collaborator Author

@Smit-create Smit-create May 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we still need a handwritten file that includes it, to be sure that all the arguments are compatible.

Yeah, you're right. ccallable needs to be updated in the LLVM backend so that it can call from C.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test_emit_header_ccallable must be in a C file, not a header file, otherwise the function will be generated twice by the C compiler and you will get linking errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

@ccallable: emit a header file
2 participants