clean up some stuff
This commit is contained in:
parent
1b14ecf5ff
commit
5e02ecd80d
10 changed files with 231 additions and 66 deletions
BIN
a.out
Executable file
BIN
a.out
Executable file
Binary file not shown.
104
src/codegen.c
104
src/codegen.c
|
@ -2,86 +2,114 @@
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
void codegen(Node node) {
|
void codegen(Node node, bool emit_type) {
|
||||||
switch(node.type) {
|
switch(node.type) {
|
||||||
case NODE_FUNCTION_CALL:
|
case NODE_FUNCTION_CALL:
|
||||||
codegen_function_call(node);
|
codegen_function_call(node.function_call);
|
||||||
break;
|
break;
|
||||||
case NODE_FUNCTION_DECL:
|
case NODE_FUNCTION_DECL:
|
||||||
codegen_function_decl(node);
|
codegen_function_decl(node.function_decl);
|
||||||
break;
|
break;
|
||||||
case NODE_FUNCTION_IMPL:
|
case NODE_FUNCTION_IMPL:
|
||||||
codegen_function_impl(node);
|
codegen_function_impl(node.function_impl);
|
||||||
break;
|
break;
|
||||||
case NODE_ARG_DECL:
|
case NODE_ARG_DECL:
|
||||||
codegen_arg_decl(node);
|
codegen_arg_decl(node.arg_decl, emit_type);
|
||||||
|
break;
|
||||||
|
case NODE_REFERENCE:
|
||||||
|
codegen_reference(node.reference, emit_type);
|
||||||
break;
|
break;
|
||||||
case NODE_NUMBER:
|
case NODE_NUMBER:
|
||||||
codegen_number(node);
|
codegen_number(node.number, emit_type);
|
||||||
|
break;
|
||||||
|
case NODE_RETURN:
|
||||||
|
codegen_return(node.ret);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
syntax_error("unexpected node %c", node.type);
|
syntax_error("unexpected node %c", node.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen_function_call(Node node) {
|
void codegen_function_call(FunctionCall node) {
|
||||||
printf("FunctionCall(%s", node.function_call.name);
|
printf("call $%s(", node.name);
|
||||||
if(Nodes_size(&node.function_call.args) > 0)
|
// printf("FunctionCall(%s", node.function_call.name);
|
||||||
printf(", ");
|
/*if(Nodes_size(&node.function_call.args) > 0)
|
||||||
for(size_t i = 0; i < Nodes_size(&node.function_call.args); i++) {
|
printf(", ");*/
|
||||||
const Node* arg = Nodes_at(&node.function_call.args, i);
|
for(size_t i = 0; i < Nodes_size(&node.args); i++) {
|
||||||
codegen(*arg);
|
const Node* arg = Nodes_at(&node.args, i);
|
||||||
|
codegen(*arg, true);
|
||||||
|
|
||||||
if(arg != Nodes_back(&node.function_call.args)) {
|
if(arg != Nodes_back(&node.args)) {
|
||||||
printf(", ");
|
printf(", ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf(")\n");
|
printf(")\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen_function_decl(Node node) {
|
void codegen_function_decl(FunctionDecl node) {
|
||||||
printf("FunctionDecl(%s, %s, ", node.function_decl.type, node.function_decl.name);
|
printf("FunctionDecl(%s, %s, ", node.type, node.name);
|
||||||
for(size_t i = 0; i < Nodes_size(&node.function_decl.args); i++) {
|
for(size_t i = 0; i < Nodes_size(&node.args); i++) {
|
||||||
const Node* arg = Nodes_at(&node.function_decl.args, i);
|
const Node* arg = Nodes_at(&node.args, i);
|
||||||
codegen(*arg);
|
codegen(*arg, true);
|
||||||
|
|
||||||
if(arg != Nodes_back(&node.function_decl.args)) {
|
if(arg != Nodes_back(&node.args)) {
|
||||||
printf(", ");
|
printf(", ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf(")\n");
|
printf(")\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen_function_impl(Node node) {
|
void codegen_function_impl(FunctionImpl node) {
|
||||||
printf("FunctionImpl(%s, %s", node.function_impl.type, node.function_impl.name);
|
printf("export function %s $%s(", node.type, node.name);
|
||||||
if(Nodes_size(&node.function_impl.args) > 0)
|
for(size_t i = 0; i < Nodes_size(&node.args); i++) {
|
||||||
printf(", ");
|
const Node* arg = Nodes_at(&node.args, i);
|
||||||
for(size_t i = 0; i < Nodes_size(&node.function_impl.args); i++) {
|
codegen(*arg, true);
|
||||||
const Node* arg = Nodes_at(&node.function_impl.args, i);
|
|
||||||
codegen(*arg);
|
|
||||||
|
|
||||||
if(arg != Nodes_back(&node.function_impl.args)) {
|
if(arg != Nodes_back(&node.args)) {
|
||||||
printf(", ");
|
printf(", ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf(") {\n\t");
|
printf(") {\n@start\n\t");
|
||||||
|
|
||||||
for(size_t i = 0; i < Nodes_size(&node.function_impl.body); i++) {
|
for(size_t i = 0; i < Nodes_size(&node.body); i++) {
|
||||||
const Node* n = Nodes_at(&node.function_impl.body, i);
|
const Node* n = Nodes_at(&node.body, i);
|
||||||
codegen(*n);
|
codegen(*n, true);
|
||||||
|
|
||||||
if(n != Nodes_back(&node.function_impl.body)) {
|
if(n != Nodes_back(&node.body)) {
|
||||||
printf("\t");
|
printf("\t");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("}\n");
|
printf("\t\n}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen_arg_decl(Node node) {
|
void codegen_arg_decl(ArgDecl node, bool emit_type) {
|
||||||
printf("ArgDecl(%s, %s)", node.arg_decl.type, node.arg_decl.name);
|
// printf("ArgDecl(%s, %s)", node.arg_decl.type, node.arg_decl.name);
|
||||||
|
if(emit_type) {
|
||||||
|
printf("%s ", node.type);
|
||||||
|
}
|
||||||
|
printf("%%%s", node.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen_number(Node node) {
|
void codegen_reference(Reference node, bool emit_type) {
|
||||||
printf("Number(%llu)", node.number.value);
|
// printf("Reference(%s)", node.reference.name);
|
||||||
|
if(emit_type) {
|
||||||
|
printf("%s ", node.type);
|
||||||
|
}
|
||||||
|
printf("%%%s", node.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_number(Number node, bool emit_type) {
|
||||||
|
// printf("Number(%llu)", node.number.value);
|
||||||
|
if(emit_type) {
|
||||||
|
printf("w ");
|
||||||
|
}
|
||||||
|
printf("%d", node.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_return(Return node) {
|
||||||
|
printf("ret ");
|
||||||
|
if(node.value != NULL) {
|
||||||
|
codegen(*node.value, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,13 @@
|
||||||
|
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
|
|
||||||
void codegen(Node node);
|
void codegen(Node node, bool emit_type);
|
||||||
void codegen_function_call(Node node);
|
void codegen_function_call(FunctionCall node);
|
||||||
void codegen_function_decl(Node node);
|
void codegen_function_decl(FunctionDecl node);
|
||||||
void codegen_arg_decl(Node node);
|
void codegen_arg_decl(ArgDecl node, bool emit_type);
|
||||||
void codegen_function_impl(Node node);
|
void codegen_function_impl(FunctionImpl node);
|
||||||
void codegen_number(Node node);
|
void codegen_reference(Reference node, bool emit_type);
|
||||||
|
void codegen_number(Number node, bool emit_type);
|
||||||
|
void codegen_return(Return node);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define COMPILER_H
|
#define COMPILER_H
|
||||||
|
|
||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
|
#include "node.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TOKEN_IDENTIFIER = 'I',
|
TOKEN_IDENTIFIER = 'I',
|
||||||
|
@ -32,6 +33,7 @@ typedef enum {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Lexer* lexer;
|
Lexer* lexer;
|
||||||
cmap_str types;
|
cmap_str types;
|
||||||
|
NodeMap symbols;
|
||||||
} Compiler;
|
} Compiler;
|
||||||
|
|
||||||
bool next(Compiler* compiler, Token* token);
|
bool next(Compiler* compiler, Token* token);
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
assert(argc > 1);
|
assert(argc > 1);
|
||||||
|
@ -38,13 +37,14 @@ int main(int argc, char** argv) {
|
||||||
{ "i64", "l" },
|
{ "i64", "l" },
|
||||||
{ "void", "" },
|
{ "void", "" },
|
||||||
}),
|
}),
|
||||||
|
.symbols = { 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
Token token;
|
Token token;
|
||||||
while(next(&compiler, &token)) {
|
while(next(&compiler, &token)) {
|
||||||
// printf("%c: %s\n", token.type, token.value);
|
// printf("%c: %s\n", token.type, token.value);
|
||||||
Node node = parse_token(&compiler, token);
|
Node node = parse_token(&compiler, token);
|
||||||
codegen(node);
|
codegen(node, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
24
src/node.h
24
src/node.h
|
@ -1,17 +1,22 @@
|
||||||
#ifndef NODE_H
|
#ifndef NODE_H
|
||||||
#define NODE_H
|
#define NODE_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <stc/cstr.h>
|
||||||
#include <stc/forward.h>
|
#include <stc/forward.h>
|
||||||
typedef struct Node Node;
|
typedef struct Node Node;
|
||||||
forward_cvec(Nodes, struct Node);
|
forward_cvec(Nodes, struct Node);
|
||||||
|
forward_cmap(NodeMap, cstr, struct Node);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NODE_FUNCTION_CALL = 'C',
|
NODE_FUNCTION_CALL = 'C',
|
||||||
NODE_FUNCTION_DECL = 'D',
|
NODE_FUNCTION_DECL = 'D',
|
||||||
NODE_FUNCTION_IMPL = 'I',
|
NODE_FUNCTION_IMPL = 'I',
|
||||||
NODE_ARG_DECL = 'A',
|
NODE_ARG_DECL = 'A',
|
||||||
|
NODE_RETURN = 'R',
|
||||||
|
NODE_REFERENCE = 'r',
|
||||||
NODE_NUMBER = 'N',
|
NODE_NUMBER = 'N',
|
||||||
} NodeType;
|
} NodeType;
|
||||||
|
|
||||||
|
@ -39,9 +44,18 @@ typedef struct {
|
||||||
} ArgDecl;
|
} ArgDecl;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
long long int value;
|
const char* type;
|
||||||
|
const char* name;
|
||||||
|
} Reference;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int value;
|
||||||
} Number;
|
} Number;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Node* value;
|
||||||
|
} Return;
|
||||||
|
|
||||||
struct Nodes;
|
struct Nodes;
|
||||||
typedef struct Node {
|
typedef struct Node {
|
||||||
NodeType type;
|
NodeType type;
|
||||||
|
@ -50,7 +64,9 @@ typedef struct Node {
|
||||||
FunctionDecl function_decl;
|
FunctionDecl function_decl;
|
||||||
FunctionImpl function_impl;
|
FunctionImpl function_impl;
|
||||||
ArgDecl arg_decl;
|
ArgDecl arg_decl;
|
||||||
|
Reference reference;
|
||||||
Number number;
|
Number number;
|
||||||
|
Return ret;
|
||||||
};
|
};
|
||||||
} Node;
|
} Node;
|
||||||
|
|
||||||
|
@ -60,4 +76,10 @@ typedef struct Node {
|
||||||
#define i_opt c_no_cmp
|
#define i_opt c_no_cmp
|
||||||
#include <stc/cvec.h>
|
#include <stc/cvec.h>
|
||||||
|
|
||||||
|
#define i_type NodeMap
|
||||||
|
#define i_is_forward
|
||||||
|
#define i_key_str
|
||||||
|
#define i_val Node
|
||||||
|
#include <stc/cmap.h>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
85
src/parser.c
85
src/parser.c
|
@ -43,23 +43,53 @@ Node parse_type(Compiler* self, const char* type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Node parse_identifier(Compiler* self, const char* name) {
|
const char* resolve_type(Compiler* self, Node node) {
|
||||||
Token token;
|
switch(node.type) {
|
||||||
next(self, &token);
|
case NODE_ARG_DECL:
|
||||||
|
return node.arg_decl.type;
|
||||||
switch(token.type) {
|
|
||||||
case TOKEN_OPAREN:
|
|
||||||
return parse_function_call(self, name);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
syntax_error("unexpected token \"%s\" after identifier \"%s\"", token.value, name);
|
syntax_error("unexpected node fed to resolve_type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Node parse_identifier(Compiler* self, const char* name) {
|
||||||
|
if(strcmp(name, "return") == 0) {
|
||||||
|
Token token;
|
||||||
|
next(self, &token);
|
||||||
|
Node* node = NULL;
|
||||||
|
|
||||||
|
if(token.type != TOKEN_SEMICOLON) {
|
||||||
|
node = malloc(sizeof(Node));
|
||||||
|
Node parsed = parse_token(self, token);
|
||||||
|
memcpy(node, &parsed, sizeof(Node));
|
||||||
|
parse_semicolon(self);
|
||||||
|
}
|
||||||
|
return (Node){ .type = NODE_RETURN, .ret = { .value = node } };
|
||||||
|
}
|
||||||
|
|
||||||
|
const NodeMap_value* symbol = NodeMap_get(&self->symbols, name);
|
||||||
|
if(symbol == NULL) {
|
||||||
|
syntax_error("undefined symbol \"%s\"", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(symbol->second.type) {
|
||||||
|
case NODE_FUNCTION_DECL:
|
||||||
|
case NODE_FUNCTION_IMPL:
|
||||||
|
return parse_function_call(self, name);
|
||||||
|
case NODE_ARG_DECL:
|
||||||
|
return (Node){
|
||||||
|
.type = NODE_REFERENCE,
|
||||||
|
.reference = { .type = resolve_type(self, symbol->second), .name = name },
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
syntax_error("unexpected symbol type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Node parse_number(Compiler* self, const char* value) {
|
Node parse_number(Compiler* self, const char* value) {
|
||||||
return (Node){
|
return (Node){
|
||||||
.type = NODE_NUMBER,
|
.type = NODE_NUMBER,
|
||||||
.number = atoll(value),
|
.number = atoi(value),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,15 +115,17 @@ Node parse_function(Compiler* self, const char* type, const char* name) {
|
||||||
if(arg_type.type == TOKEN_CPAREN) {
|
if(arg_type.type == TOKEN_CPAREN) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
const cmap_str_value* type = cmap_str_get(&self->types, arg_type.value);
|
||||||
|
|
||||||
Token arg_name;
|
Token arg_name;
|
||||||
next(self, &arg_name);
|
next(self, &arg_name);
|
||||||
|
|
||||||
Nodes_push(&args,
|
Node arg_decl = (Node){
|
||||||
(Node){
|
.type = NODE_ARG_DECL,
|
||||||
.type = NODE_ARG_DECL,
|
.arg_decl = { .type = cstr_str(&type->second), .name = arg_name.value },
|
||||||
.arg_decl = { .type = arg_type.value, .name = arg_name.value },
|
};
|
||||||
});
|
Nodes_push(&args, arg_decl);
|
||||||
|
NodeMap_insert(&self->symbols, cstr_from(arg_name.value), arg_decl);
|
||||||
|
|
||||||
Token token;
|
Token token;
|
||||||
next(self, &token);
|
next(self, &token);
|
||||||
|
@ -109,19 +141,29 @@ Node parse_function(Compiler* self, const char* type, const char* name) {
|
||||||
break; // only reached if didnt continue or error
|
break; // only reached if didnt continue or error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cmap_str_value* real_type = cmap_str_get(&self->types, type);
|
||||||
|
const char* real_type_cstr = cstr_str(&real_type->second);
|
||||||
|
|
||||||
Token token;
|
Token token;
|
||||||
|
Node function_node;
|
||||||
if(next(self, &token)) {
|
if(next(self, &token)) {
|
||||||
switch(token.type) {
|
switch(token.type) {
|
||||||
case TOKEN_SEMICOLON:
|
case TOKEN_SEMICOLON:
|
||||||
return parse_function_decl(self, type, name, args);
|
function_node = parse_function_decl(self, real_type_cstr, name, args);
|
||||||
|
break;
|
||||||
case TOKEN_OBRACE:
|
case TOKEN_OBRACE:
|
||||||
return parse_function_impl(self, type, name, args);
|
function_node = parse_function_impl(self, real_type_cstr, name, args);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
syntax_error("expected semicolon or opening brace found, %s", token.value);
|
syntax_error("expected semicolon or opening brace found, %s", token.value);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
syntax_error("expected token, found eof");
|
syntax_error("expected token, found eof");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("inserting %s into symbols\n", name);
|
||||||
|
NodeMap_insert(&self->symbols, cstr_from(name), function_node);
|
||||||
|
return function_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node parse_function_decl(Compiler* self, const char* type, const char* name, Nodes args) {
|
Node parse_function_decl(Compiler* self, const char* type, const char* name, Nodes args) {
|
||||||
|
@ -142,6 +184,15 @@ Node parse_function_impl(Compiler* self, const char* type, const char* name, Nod
|
||||||
|
|
||||||
Node parse_function_call(Compiler* self, const char* name) {
|
Node parse_function_call(Compiler* self, const char* name) {
|
||||||
printf("parse function call %s\n", name);
|
printf("parse function call %s\n", name);
|
||||||
|
Token token;
|
||||||
|
next(self, &token);
|
||||||
|
switch(token.type) {
|
||||||
|
case TOKEN_OPAREN:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
syntax_error("unexpected token \"%s\" after function name", token.value);
|
||||||
|
}
|
||||||
|
|
||||||
Nodes args = parse_until(self, TOKEN_CPAREN);
|
Nodes args = parse_until(self, TOKEN_CPAREN);
|
||||||
|
|
||||||
parse_semicolon(self);
|
parse_semicolon(self);
|
||||||
|
|
41
test.s
Normal file
41
test.s
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
.text
|
||||||
|
.balign 16
|
||||||
|
.globl sayhi
|
||||||
|
sayhi:
|
||||||
|
hint #34
|
||||||
|
stp x29, x30, [sp, -32]!
|
||||||
|
mov x29, sp
|
||||||
|
str x19, [x29, 24]
|
||||||
|
mov w19, w0
|
||||||
|
mov w0, #72
|
||||||
|
bl putchar
|
||||||
|
mov w0, w19
|
||||||
|
mov w19, w0
|
||||||
|
mov w0, #105
|
||||||
|
bl putchar
|
||||||
|
mov w0, w19
|
||||||
|
bl putchar
|
||||||
|
mov w0, #5
|
||||||
|
ldr x19, [x29, 24]
|
||||||
|
ldp x29, x30, [sp], 32
|
||||||
|
ret
|
||||||
|
.type sayhi, @function
|
||||||
|
.size sayhi, .-sayhi
|
||||||
|
/* end function sayhi */
|
||||||
|
|
||||||
|
.text
|
||||||
|
.balign 16
|
||||||
|
.globl main
|
||||||
|
main:
|
||||||
|
hint #34
|
||||||
|
stp x29, x30, [sp, -16]!
|
||||||
|
mov x29, sp
|
||||||
|
mov w0, #74
|
||||||
|
bl sayhi
|
||||||
|
ldp x29, x30, [sp], 16
|
||||||
|
ret
|
||||||
|
.type main, @function
|
||||||
|
.size main, .-main
|
||||||
|
/* end function main */
|
||||||
|
|
||||||
|
.section .note.GNU-stack,"",@progbits
|
14
test.ssa
Normal file
14
test.ssa
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
export function w $sayhi(w %char) {
|
||||||
|
@start
|
||||||
|
call $putchar(w 72)
|
||||||
|
call $putchar(w 105)
|
||||||
|
call $putchar(w %char)
|
||||||
|
ret 5
|
||||||
|
}
|
||||||
|
|
||||||
|
export function $main() {
|
||||||
|
@start
|
||||||
|
call $sayhi(w 74)
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
9
test.txt
9
test.txt
|
@ -1,8 +1,13 @@
|
||||||
i32 putchar(i32 char);
|
i32 putchar(i32 char);
|
||||||
|
|
||||||
void sayhi() {
|
i32 sayhi(i32 char) {
|
||||||
putchar(72);
|
putchar(72);
|
||||||
putchar(105);
|
putchar(105);
|
||||||
|
putchar(char);
|
||||||
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
sayhi();
|
void main() {
|
||||||
|
sayhi(74);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue