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

LLVM-based Compiler #578

Merged
merged 31 commits into from
Aug 12, 2023
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c749387
add plumbing for llvm-based compiler
ctiedt Jun 30, 2023
489b277
compile llvm ir with clang
ctiedt Jun 30, 2023
f956026
Merge remote-tracking branch 'origin/main' into inkwell-compiler
ctiedt Jul 13, 2023
1694762
start work on builtins, function calls
ctiedt Jul 13, 2023
9427241
free globals at end of program
ctiedt Jul 13, 2023
7a4e8a2
support ifElse and printing main output
ctiedt Jul 14, 2023
94f85cb
add support for closures
ctiedt Jul 20, 2023
8e7eb44
deref value when using reference instruction
ctiedt Jul 21, 2023
0f82e2f
reorganize candy_rt, add structs
ctiedt Jul 21, 2023
cedd1f5
implement list
ctiedt Jul 22, 2023
fc6dd1c
add support for indirect calls; make fibonacci run
ctiedt Aug 3, 2023
f8808d9
Merge remote-tracking branch 'origin/main' into inkwell-compiler
ctiedt Aug 3, 2023
3d9897e
remove unnecessary allocations in runtime
ctiedt Aug 3, 2023
f11eabb
Apply suggestions from code review
ctiedt Aug 10, 2023
f56f1a8
clean up runtime and codegen
ctiedt Aug 10, 2023
91f26bf
Merge branch 'inkwell-compiler' of https://github.com/candy-lang/cand…
ctiedt Aug 10, 2023
cdb1cb9
remove int.candy example
ctiedt Aug 10, 2023
874c299
fix packages after renaming backend_inkwell
ctiedt Aug 10, 2023
832e868
replace candy_type with candy_value
ctiedt Aug 10, 2023
4c28b54
deduplicate more of string allocation process
ctiedt Aug 10, 2023
05bf0d9
ignore responsibilities
ctiedt Aug 10, 2023
65a905c
Update compiler/backend_inkwell/src/lib.rs
ctiedt Aug 10, 2023
daee6f4
Update compiler/backend_inkwell/src/lib.rs
ctiedt Aug 10, 2023
8fb87a1
extract global creation into function
ctiedt Aug 10, 2023
8a43121
add inkwell feature to cli
ctiedt Aug 10, 2023
aa628c6
rename candy runtime
ctiedt Aug 10, 2023
008ab8e
address requested changes
ctiedt Aug 12, 2023
c97ccc4
download llvm in ci
ctiedt Aug 12, 2023
7681ee8
Merge remote-tracking branch 'origin/main' into inkwell-compiler
ctiedt Aug 12, 2023
98b9da4
undo workspace formatting
ctiedt Aug 12, 2023
b8467e6
specify exact llvm action version in ci
ctiedt Aug 12, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/labels.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
- compiler/frontend/**/*
'P: Compiler: Fuzzer':
- compiler/fuzzer/**/*
'P: Compiler: Inkwell Backend':
- compiler/backend_inkwell/**/*
'P: Compiler: Language Server':
- compiler/language_server/**/*
'P: Compiler: VM':
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,9 @@ coverage/
.buildlog/
.history
.svn/

# LLVM Artefacts
*.o
*.a
*.ll
*.s
48 changes: 48 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[workspace]

members = [
"compiler/backend_inkwell",
"compiler/cli",
"compiler/frontend",
"compiler/fuzzer",
Expand Down
10 changes: 10 additions & 0 deletions compiler/backend_inkwell/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "candy_backend_inkwell"
version = "0.1.0"
edition = "2021"

[dependencies]
candy_frontend = { version = "0.1.0", path = "../frontend" }
inkwell = { version = "0.2.0", features = ["llvm15-0"] }
itertools = "0.11.0"
llvm-sys = { version = "150", features = ["prefer-dynamic"] }
9 changes: 9 additions & 0 deletions compiler/backend_inkwell/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Candy Inkwell Compiler

This crate provides an LLVM-based backend for the Candy compiler using the inkwell crate.
It is highly experimental and still doesn't support many of Candy's features.

## Requirements

You currently need to have LLVM 15 installed on your system.
You also need to have the `llc` and `clang` commands available.
10 changes: 10 additions & 0 deletions compiler/backend_inkwell/candy_runtime/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CC=clang

candy_runtime.a: candy_runtime.o candy_builtin.o
ar rcs $@ $^

%.o: %.c %.h

.PHONY: clean
clean:
rm -f *.o *.a
152 changes: 152 additions & 0 deletions compiler/backend_inkwell/candy_runtime/candy_builtin.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "candy_runtime.h"

const candy_value_t *candy_builtin_equals(candy_value_t *left, candy_value_t *right)
{
if (left
->type != right->type)
{
return &__internal_false;
}
switch (left->type)
{
case CANDY_TYPE_INT:
return to_candy_bool(left->value.integer == right->value.integer);
break;
case CANDY_TYPE_TAG:
return to_candy_bool(strcmp(left->value.text, right->value.text) == 0);
default:
return &__internal_false;
}
}

const candy_value_t *candy_builtin_if_else(candy_value_t *condition, candy_value_t *then, candy_value_t *otherwise)
{
candy_value_t *body = candy_tag_to_bool(condition) ? then : otherwise;
candy_function function = (body->value).function.function;
candy_value_t *environment = (body->value).function.environment;
return function(environment);
}

candy_value_t *candy_builtin_int_add(candy_value_t *left, candy_value_t *right)
{
return make_candy_int(left->value.integer + right->value.integer);
}

candy_value_t *candy_builtin_int_subtract(candy_value_t *left, candy_value_t *right)
{
return make_candy_int(left->value.integer - right->value.integer);
}

candy_value_t *candy_builtin_int_bit_length(candy_value_t *value)
{
long long int_value = value->value.integer;
ctiedt marked this conversation as resolved.
Show resolved Hide resolved
int shifts = 0;
while (int_value)
{
int_value = int_value >> shifts;
shifts++;
}
ctiedt marked this conversation as resolved.
Show resolved Hide resolved
return make_candy_int(shifts);
}

candy_value_t *candy_builtin_int_bitwise_and(candy_value_t *left, candy_value_t *right)
{
return make_candy_int(left->value.integer & right->value.integer);
}

candy_value_t *candy_builtin_int_bitwise_or(candy_value_t *left, candy_value_t *right)
{
return make_candy_int(left->value.integer | right->value.integer);
}

candy_value_t *candy_builtin_int_bitwise_xor(candy_value_t *left, candy_value_t *right)
{
return make_candy_int(left->value.integer ^ right->value.integer);
}

const candy_value_t *candy_builtin_int_compare_to(candy_value_t *left, candy_value_t *right)
{
int64_t left_value = left->value.integer;
int64_t right_value = right->value.integer;
if (left_value < right_value)
{
return &__internal_less;
}
else if (left_value == right_value)
{
return &__internal_equal;
}
else
{
return &__internal_greater;
}
}

candy_value_t *candy_builtin_list_length(const candy_value_t *list)
{
size_t index = 0;
while (list->value.list[index] != NULL)
{
index++;
}
return make_candy_int(index);
}

const candy_value_t *candy_builtin_print(candy_value_t *value)
{
print_candy_value(value);
printf("\n");
return &__internal_nothing;
}

candy_value_t *candy_builtin_struct_get(candy_value_t *structure, candy_value_t *key)
{
size_t index = 0;
while (!candy_tag_to_bool(candy_builtin_equals(structure->value.structure.keys[index], key)))
{
index++;
}
return structure->value.structure.values[index];
}

candy_value_t *candy_builtin_struct_get_keys(candy_value_t *structure)
{
return make_candy_list(structure->value.structure.keys);
}

const candy_value_t *candy_builtin_struct_has_key(candy_value_t *structure, candy_value_t *key)
{
size_t index = 0;
while (structure->value.structure.keys[index] != NULL)
{
if (candy_tag_to_bool(candy_builtin_equals(structure->value.structure.keys[index], key)))
{
return &__internal_true;
}
}
return &__internal_false;
}

const candy_value_t *candy_builtin_type_of(candy_value_t *value)
{
switch (value->type)
{
case CANDY_TYPE_INT:
return &__internal_int;
case CANDY_TYPE_TEXT:
return &__internal_text;
case CANDY_TYPE_TAG:
return &__internal_tag;
case CANDY_TYPE_LIST:
return &__internal_list;
case CANDY_TYPE_STRUCT:
return &__internal_struct;
case CANDY_TYPE_FUNCTION:
return &__internal_function;
default:
candy_panic(&__internal_unknown);
}
}
17 changes: 17 additions & 0 deletions compiler/backend_inkwell/candy_runtime/candy_builtin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "candy_runtime.h"

const candy_value_t *candy_builtin_equals(candy_value_t *left, candy_value_t *right);
const candy_value_t *candy_builtin_if_else(candy_value_t *condition, candy_value_t *then, candy_value_t *otherwise);
candy_value_t *candy_builtin_int_add(candy_value_t *left, candy_value_t *right);
candy_value_t *candy_builtin_int_subtract(candy_value_t *left, candy_value_t *right);
candy_value_t *candy_builtin_int_bit_length(candy_value_t *value);
candy_value_t *candy_builtin_int_bitwise_and(candy_value_t *left, candy_value_t *right);
candy_value_t *candy_builtin_int_bitwise_or(candy_value_t *left, candy_value_t *right);
candy_value_t *candy_builtin_int_bitwise_xor(candy_value_t *left, candy_value_t *right);
const candy_value_t *candy_builtin_int_compare_to(candy_value_t *left, candy_value_t *right);
candy_value_t *candy_builtin_list_length(const candy_value_t *list);
const candy_value_t *candy_builtin_print(candy_value_t *value);
candy_value_t *candy_builtin_struct_get(candy_value_t *structure, candy_value_t *key);
candy_value_t *candy_builtin_struct_get_keys(candy_value_t *structure);
const candy_value_t *candy_builtin_struct_has_key(candy_value_t *structure, candy_value_t *key);
const candy_value_t *candy_builtin_type_of(candy_value_t *value);
Loading