Skip to content

Commit

Permalink
require extenally defined functions to be declared as external
Browse files Browse the repository at this point in the history
  • Loading branch information
dosisod committed Oct 19, 2020
1 parent d76d245 commit f5e268b
Show file tree
Hide file tree
Showing 11 changed files with 67 additions and 0 deletions.
4 changes: 4 additions & 0 deletions docs/c-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ and in Skull:
```python
# hello.sk
external hello
hello[]
return 0
Expand All @@ -31,6 +33,7 @@ Now, to compile these files together:
```
$ skull hello.sk -- hello.c
$ ./hello
hello from hello.c!
```

Everything after `--` is passed as arguments to `cc`, in this case, `hello.c`.
Expand All @@ -41,6 +44,7 @@ Skull can also compile `.o` and `.so` files, but you will need to compile them y
$ cc -c hello.c
$ skull hello.sk -- hello.o
$ ./hello
hello from hello.c!
```

For the time being, Skull can only run C functions prototypes like: `void f(void)`
Expand Down
6 changes: 6 additions & 0 deletions docs/skull/llvm/ast.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ LLVMValueRef llvm_make_div(Variable *var, const Token *lhs, const Token *rhs)

> Build LLVM for assining division of `lhs` and `rhs` to `var`.
```c
void declare_external_function(AstNode *node)
```
> Store function name of externaly declared function in `node`.
```c
void llvm_make_function(AstNode *node)
```
Expand Down
39 changes: 39 additions & 0 deletions skull/llvm/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ static LLVMModuleRef module;

extern LLVMBuilderRef builder;

#define EXTERNAL_FUNCTIONS_MAX 256
unsigned external_functions = 0;
char *external_function[EXTERNAL_FUNCTIONS_MAX] = {0};

void llvm_assign_identifier(Variable *const var, const AstNode *const node);

/*
Expand All @@ -61,6 +65,12 @@ void str_to_llvm_ir(char *const str_, LLVMValueRef func_, LLVMModuleRef module_)
node_to_llvm_ir(node);
free_ast_tree(node);
free(str);

char **current_function = external_function;
while (*current_function) {
free(*current_function);
current_function++;
}
}

/*
Expand All @@ -82,6 +92,10 @@ void node_to_llvm_ir(AstNode *node) {
llvm_make_if(node);
}

else if (node->node_type == AST_NODE_EXTERNAL) {
declare_external_function(node);
}

else if (
node->node_type == AST_NODE_IDENTIFIER &&
node->token->next &&
Expand Down Expand Up @@ -375,6 +389,18 @@ LLVMValueRef llvm_make_div(Variable *var, const Token *lhs, const Token *rhs) {
return div;
}

/*
Store function name of externaly declared function in `node`.
*/
void declare_external_function(AstNode *node) {
char32_t *const tmp = token_str(node->token->next);
char *const func_name = c32stombs(tmp);
free(tmp);

external_function[external_functions] = func_name;
external_functions++;
}

/*
Builds a function declaration from `node`.
*/
Expand All @@ -390,6 +416,19 @@ void llvm_make_function(AstNode *node) {

char32_t *const tmp = token_str(node->token);
char *const func_name = c32stombs(tmp);

char **current_function = external_function;
while (*current_function) {
if (strcmp(*current_function, func_name) == 0) {
break;
}
current_function++;
}

if (!*current_function) {
PANIC(FMT_ERROR(U"external function \"%\" missing external declaration", { .real = tmp }));
}

free(tmp);

LLVMValueRef function = LLVMAddFunction(
Expand Down
1 change: 1 addition & 0 deletions skull/llvm/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
void str_to_llvm_ir(char *const, LLVMValueRef, LLVMModuleRef);
void node_to_llvm_ir(AstNode *);

void declare_external_function(AstNode *);
void llvm_make_return(AstNode *);
void llvm_make_var_def(AstNode **);
void llvm_make_if(AstNode *);
Expand Down
2 changes: 2 additions & 0 deletions test/docs/c-integration/hello.sk
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
external hello

hello[]

return 0
6 changes: 6 additions & 0 deletions test/sh/_multiple_externals.sk.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
; ModuleID = './test/sh/multiple_externals.sk'
source_filename = "./test/sh/multiple_externals.sk"

define i64 @main() {
entry:
}
1 change: 1 addition & 0 deletions test/sh/error/missing_external.sk
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x[]
2 changes: 2 additions & 0 deletions test/sh/main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ test "mult_int_consts.sk"
test "mult_float_consts.sk"
test "div_int_consts.sk"
test "div_float_consts.sk"
test "multiple_externals.sk"

test_err "missing_file_extension_fails" "missing required \".sk\" extension, exiting"
test_err ".sk" "\".sk\" is not a valid name, exiting"
Expand Down Expand Up @@ -102,6 +103,7 @@ test_err "error/sub_mismatched_consts.sk" "Compilation error: cannot subtract \"
test_err "error/mult_mismatched_consts.sk" "Compilation error: cannot multiply \"1\" and \"\"fail\"\""
test_err "error/div_mismatched_consts.sk" "Compilation error: cannot divide \"1\" and \"\"fail\"\""
test_err "error/assign_mismatch_var_type.sk" "Compilation error: type mismatch: expected type \"bool\""
test_err "error/missing_external.sk" "Compilation error: external function \"x\" missing external declaration"

touch test/sh/error/read_protected.sk
chmod 200 test/sh/error/read_protected.sk
Expand Down
2 changes: 2 additions & 0 deletions test/sh/multiple_externals.sk
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
external a
external b
2 changes: 2 additions & 0 deletions test/sh/nodes_after_call_not_ignored.sk
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
external x

x[]

return 1
2 changes: 2 additions & 0 deletions test/sh/simple_function_call.sk
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
external x

x[]

0 comments on commit f5e268b

Please sign in to comment.