Skip to content
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

Documentation on new syntax #13

Closed
iacore opened this issue Jan 28, 2023 · 4 comments
Closed

Documentation on new syntax #13

iacore opened this issue Jan 28, 2023 · 4 comments

Comments

@iacore
Copy link
Contributor

iacore commented Jan 28, 2023

Hello, thanking for making this. I have no idea how to use this language though. How do I do FFI (e.g. call C functions)?

@vekatze
Copy link
Owner

vekatze commented Jan 28, 2023

Thank you for your interest. As you can see, this is a WIP project. So FFI is not fully supported yet.

However, technically, you can achieve it as follows.


(1) Create a project via neut build foo

(2) cd to the project and edit the file in source into something like this:

define main(): i64 =
  magic external(myFunction, 3: i64) // general form: magic external(FUNCTION_NAME, ARG_1, ..., ARG_N)
end

(3) Run neut build at the root of the project. This should result in an error like this:

error: the child process `clang` failed with the following message (exitcode = 1):
       Undefined symbols for architecture x86_64:
         "_myFunction", referenced from:
             _main in buz.o
             _this.buz::main in buz.o
       ld: symbol(s) not found for architecture x86_64
       clang: error: linker command failed with exit code 1 (use -v to see invocation)

... and we now have an LLVM IR in /target/artifact/foo.ll. The head of the file should be something like this:

declare fastcc i8* @free(i8*)
declare fastcc i8* @malloc(i8*)
declare fastcc i8* @myFunction(i8*)
(...)

We can use this ordinary LLVM IR to achieve FFI.

(4) Create test.c at the root of the repository with the following content:

int myFunction(int input) {
  return input * 3;
}

(5) Run clang test.c target/artifact/buz.ll. This should create the usual a.out.

(6) Execute a.out and see the result:

~/Desktop/foo
❯ ./a.out
~/Desktop/foo
❯ $?
zsh: command not found: 9 # ← (= 3 * 3)

... Yes, tedious. The beloved flavor of a WIP project.

I'll add neut build --emit-llvm or something like that to emit LLVM IR without clang errors in some future, but since I'm recently rewriting this project for better formulation, it might take a while. (I'm currently reformalizing arrays, and I'll also have to update the readme, etc.)

For the time being, you might be able to get rough idea of the new syntax via the (embarrassingly sketchy) files in /test/data/.

I hope you enjoy.

@iacore
Copy link
Contributor Author

iacore commented Jan 29, 2023

Thanks!

@vekatze vekatze closed this as completed Jan 29, 2023
@iacore
Copy link
Contributor Author

iacore commented Feb 2, 2023

The generated LLVM is not quite right. I think it works only based on platform ABI.

The signature is not right:
declare fastcc i8* @myFunction(i8*)

LLVM IR generated by test.c

; Function Attrs: noinline nounwind optnone
define dso_local i32 @myFunction(i32 noundef %input) #0 {
entry:
  %input.addr = alloca i32, align 4
  store i32 %input, ptr %input.addr, align 4
  %0 = load i32, ptr %input.addr, align 4
  %mul = mul nsw i32 %0, 3
  ret i32 %mul
}

test.zig

export fn myFunction(i: i32) i32 {
    return i * 3;
}
define dso_local i32 @myFunction(i32 %0) #0 !dbg !2109 {

@vekatze
Copy link
Owner

vekatze commented Feb 2, 2023

Good catch, thanks. I think I need to add a way to specify the signature of an external function. I'll add it to my todo list.

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

No branches or pull requests

2 participants