Author | Jakob Wakeling <[email protected]> |
Date | 2023-05-02 11:13:39 |
Commit | 4bdd6fc6552ec5e4bc4d6c05c7f84ea03b3bc612 |
Parent | 6dd92231459df661805b3d79c648ceb86f29413c |
Implement zero value variable initialisation
Diffstat
M | examples/main.g | | | 3 | +-- |
M | src/analyse.c | | | 2 | +- |
M | src/llvm.c | | | 32 | ++++++++++++++++++++++++++++---- |
M | src/parse.c | | | 3 | ++- |
M | src/type.h | | | 1 | + |
5 files changed, 33 insertions, 8 deletions
diff --git a/examples/main.g b/examples/main.g index dc809b6..02cf938 100644 --- a/examples/main.g +++ b/examples/main.g @@ -1,5 +1,4 @@ main :: proc() -> s64 { - var := 42 + 8; - var += 2; + var: s64; return var; } diff --git a/src/analyse.c b/src/analyse.c index d1a0e1f..3226257 100644 --- a/src/analyse.c +++ b/src/analyse.c @@ -61,7 +61,7 @@ static void analyse_stmt_decl(ast *a, syt *st) { } /* If the declaration is already typed, then ensure that it matches */ - if (A.t) { if (A.t != t) { + if (A.t) { if (t != NULL && A.t != t) { error(1, "%s:%zu:%zu: error: incorrect type", "", A.ln + 1, A.cl + 1); }} diff --git a/src/llvm.c b/src/llvm.c index 5eeb3e6..2d917b3 100644 --- a/src/llvm.c +++ b/src/llvm.c @@ -40,6 +40,7 @@ static LLVMValueRef llvm_int(ast *a); static inline void llvm_init(void); static inline void llvm_free(void); static LLVMTypeRef llvm_type(type *t); +static LLVMValueRef llvm_ival(type *t); #define A (*a) #define C (a->c.a) /* AST child shorthand "C[i]" */ @@ -108,7 +109,7 @@ static LLVMValueRef llvm_stmt_compound(ast *a, syt *st) { static LLVMValueRef llvm_stmt_decl(ast *a, syt *st) { assert(a->k == AK_DECL); - if (C[0]->k == AK_PROC) { + if (a->c.al && C[0]->k == AK_PROC) { /* TODO handle procedure arguments if present */ LLVMTypeRef ft = LLVMFunctionType(llvm_type(C[0]->t), NULL, 0, 0); LLVMValueRef f = LLVMAddFunction(llvm_module, a->s, ft); @@ -119,13 +120,15 @@ static LLVMValueRef llvm_stmt_decl(ast *a, syt *st) { llvm_expr_proc(C[0], st); a->llvm_t = ft; a->llvm_v = f; } else { - if (a->p->k == AK_PROG) { + if (a->p->k == AK_PROG) { /* Global */ LLVMValueRef v = LLVMAddGlobal(llvm_module, llvm_type(A.t), a->s); - LLVMSetInitializer(v, llvm_expr(C[0], st)); a->llvm_v = v; + LLVMSetInitializer(v, a->c.al ? llvm_expr(C[0], st) : llvm_ival(a->t)); + a->llvm_v = v; } - else { + else { /* Local */ LLVMValueRef v = LLVMBuildAlloca(llvm_builder, llvm_type(A.t), a->s); - LLVMBuildStore(llvm_builder, llvm_expr(C[0], st), v); a->llvm_v = v; + LLVMBuildStore(llvm_builder, a->c.al ? llvm_expr(C[0], st) : llvm_ival(a->t), v); + a->llvm_v = v; } } @@ -276,3 +279,20 @@ static LLVMTypeRef llvm_type(type *t) { default: { return NULL; } break; } } + +/* Return the default value for a G type. */ +static LLVMValueRef llvm_ival(type *t) { + switch (t->k) { + case TY_UINT: case TY_SINT: { return LLVMConstInt(LLVMIntType(64), 0, false); } break; + case TY_U8: case TY_S8: { return LLVMConstInt(LLVMIntType(8), 0, false); } break; + case TY_U16: case TY_S16: { return LLVMConstInt(LLVMIntType(16), 0, false); } break; + case TY_U32: case TY_S32: { return LLVMConstInt(LLVMIntType(32), 0, false); } break; + case TY_U64: case TY_S64: { return LLVMConstInt(LLVMIntType(64), 0, false); } break; + case TY_U128: case TY_S128: { return LLVMConstInt(LLVMIntType(128), 0, false); } break; + case TY_F16: { return LLVMConstReal(LLVMHalfType(), 0.0); } break; + case TY_F32: { return LLVMConstReal(LLVMFloatType(), 0.0); } break; + case TY_F64: { return LLVMConstReal(LLVMDoubleType(), 0.0); } break; + case TY_F128: { return LLVMConstReal(LLVMFP128Type(), 0.0); } break; + default: { return NULL; } break; + } +} diff --git a/src/parse.c b/src/parse.c index aa9b2ec..f4f8160 100644 --- a/src/parse.c +++ b/src/parse.c @@ -120,7 +120,6 @@ static ast *parse_stmt_decl(lex *l, syt *st) { lex_kind(l, TK_COLON); /* Store the declaration's type if one is specified */ - /* TODO store type when one is specified */ if (T.k == TK_ID) { ast *s = syt_search_h(st, T.h, T.s); @@ -359,6 +358,7 @@ void ast_print(ast *a, UINT i) { printf("%zu:%zu: %s: %s", a->ln + 1, a->cl + 1, ast_ks[a->k], a->s); switch (a->k) { + case AK_DECL: { if (a->t == NULL) { break; }} case AK_PROC: case AK_INT: { printf(" -> %s", a->t->s); } break; default: {} break; } diff --git a/src/type.h b/src/type.h index ec7bb41..e818f2f 100644 --- a/src/type.h +++ b/src/type.h @@ -52,6 +52,7 @@ typedef enum { TF_NUM = TF_INT | TF_FLT | TF_CLX, } type_f; +/* k : Kind, f : Flags, l : Length, s : String */ typedef struct type_s { type_k k; type_f f; s64 l; char *s; struct type_s *base;