aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2019-08-01 20:36:51 +0200
committerdec05eba <dec05eba@protonmail.com>2020-07-25 14:36:46 +0200
commit4ca3b74621c3608de42a91730a71892d9d7c27b5 (patch)
treeae6ed7a1c37fc7fe32b3f763b839e65fe6becbeb
parent0f26e1d204d3a3026ca3edfc4c6bd9638b2632e7 (diff)
Remove nullable... it's bad to have magic. Static analysis can do it instead
-rwxr-xr-xbuild.sh2
-rw-r--r--doc/Documentation.md8
-rw-r--r--include/ast.h4
-rw-r--r--include/nullable.h24
-rw-r--r--src/asm/x86_64.c2
-rw-r--r--src/ast.c24
-rw-r--r--src/bytecode/bytecode.c8
-rw-r--r--src/compiler.c2
-rw-r--r--src/nullable.c8
-rw-r--r--src/parser.c12
-rw-r--r--src/ssa/ssa.c8
-rw-r--r--tests/bytecode.amal2
12 files changed, 37 insertions, 67 deletions
diff --git a/build.sh b/build.sh
index 8470eb6..cac8275 100755
--- a/build.sh
+++ b/build.sh
@@ -10,7 +10,7 @@ if [ -z "$CC" ]; then
CC=cc
fi
-CFLAGS="-Wall -Wextra -Werror -Wno-format-security -Wnull-dereference -Wjump-misses-init -std=c89 -D_GNU_SOURCE "
+CFLAGS="-Wall -Wextra -Werror -Wno-format-security -Wnull-dereference -std=c89 -D_GNU_SOURCE "
LIBS="-pthread "
if [ ! -z "$SANITIZE_ADDRESS" ]; then
diff --git a/doc/Documentation.md b/doc/Documentation.md
index 01b6a6b..2fcfe07 100644
--- a/doc/Documentation.md
+++ b/doc/Documentation.md
@@ -65,7 +65,7 @@ The versions in the header only changes for every release, not every change.
# Bytecode instructions
## Instructions layout
-|Type |Field |Description |
-|------------|-----------------|---------------------------------------------------------------------------|
-|u32 |Instructions size|The size of the instructions section, in bytes. |
-|Instruction*|Instructions data|The instructions data. Each instructions begins with an opcode, see #Opcode| \ No newline at end of file
+|Type |Field |Description |
+|-----------|-----------------|---------------------------------------------------------------------------|
+|u32 |Instructions size|The size of the instructions section, in bytes. |
+|Instruction|Instructions data|The instructions data. Each instructions begins with an opcode, see #Opcode| \ No newline at end of file
diff --git a/include/ast.h b/include/ast.h
index 6a40980..9f01b1b 100644
--- a/include/ast.h
+++ b/include/ast.h
@@ -88,8 +88,6 @@ struct Ast {
SsaRegister ssa_reg;
};
-DefineNullablePtrType(Ast);
-
struct Scope {
Buffer/*<Ast*>*/ ast_objects;
HashMap/*(key=BufferView, value=Ast<LhsExpr>*)*/ named_objects;
@@ -160,7 +158,7 @@ struct LhsExpr {
bool is_const;
BufferView var_name;
VariableType type;
- NullablePtr(Ast) rhs_expr;
+ Ast *rhs_expr;
};
struct AssignmentExpr {
diff --git a/include/nullable.h b/include/nullable.h
index 6c4d3a7..f84100b 100644
--- a/include/nullable.h
+++ b/include/nullable.h
@@ -3,27 +3,7 @@
struct __nullable_type_dummy{ int _; };
-int assert_not_null(void *val);
-
-#ifdef DEBUG
-#define DefineNullablePtrType(type) \
- typedef struct type##_nullable type##_nullable; \
- struct type##_nullable { \
- type *value; \
- }
-#define NullablePtr(type) type##_nullable
-#define nullable_unwrap(nullable_type) \
- (assert_not_null((nullable_type).value) ? ((nullable_type).value) : NULL)
-#define nullable_assign(nullable_type, new_value) ((nullable_type).value = (new_value))
-#define is_not_null(nullable_type) ((nullable_type).value != NULL)
-#define nullable_raw(nullable_type) ((nullable_type).value)
-#else
-#define DefineNullablePtrType(type)
-#define NullablePtr(type) type*
-#define nullable_unwrap(value) value
-#define nullable_assign(nullable_type, new_value) ((nullable_type) = (new_value))
-#define is_not_null(nullable_type) ((nullable_type) != NULL)
-#define nullable_raw(nullable_type) (nullable_type)
-#endif
+/* Used by static analysis tool to find null-pointer dereference errors */
+#define nullable
#endif
diff --git a/src/asm/x86_64.c b/src/asm/x86_64.c
index 16e6bc6..e246fbc 100644
--- a/src/asm/x86_64.c
+++ b/src/asm/x86_64.c
@@ -382,4 +382,4 @@ int asm_ret(Asm *self, u16 bytes) {
am_memcpy(self->code_it, &bytes, sizeof(bytes));
}
return 0;
-} \ No newline at end of file
+}
diff --git a/src/ast.c b/src/ast.c
index db2f61d..e28b072 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -107,7 +107,7 @@ void lhsexpr_init(LhsExpr *self, bool is_extern, bool is_pub, bool is_const, Buf
self->type.type = VARIABLE_TYPE_NONE;
self->type.value.variable = NULL;
self->var_name = var_name;
- nullable_assign(self->rhs_expr, NULL);
+ self->rhs_expr = NULL;
}
void assignmentexpr_init(AssignmentExpr *self, Ast *lhs_expr, Ast *rhs_expr) {
@@ -333,11 +333,11 @@ static BufferView variable_type_get_name(VariableType *self) {
static LhsExpr* lhsexpr_resolve_rhs(LhsExpr *self, AstCompilerContext *context) {
LhsExpr *rhs_resolved_type;
- ast_resolve(nullable_unwrap(self->rhs_expr), context);
- if(ast_is_decl(nullable_unwrap(self->rhs_expr)))
+ ast_resolve(self->rhs_expr, context);
+ if(ast_is_decl(self->rhs_expr))
rhs_resolved_type = self;
else
- rhs_resolved_type = nullable_unwrap(self->rhs_expr)->resolve_data.type;
+ rhs_resolved_type = self->rhs_expr->resolve_data.type;
return rhs_resolved_type;
}
@@ -354,15 +354,15 @@ static void lhsexpr_resolve(Ast *ast, AstCompilerContext *context) {
the parameters and return types have been resolved as recursive function calls should
be allowed but recursive function calls still require parameters and return types to be known.
*/
- if(is_not_null(self->rhs_expr)) {
+ if(self->rhs_expr) {
LhsExpr *rhs_resolve_type;
- if(nullable_unwrap(self->rhs_expr)->type == AST_FUNCTION_DECL) {
+ if(self->rhs_expr->type == AST_FUNCTION_DECL) {
/*
The function declaration itself always resolves the signature, but we also do it here because we
want to have the signature solved before setting the lhs expr as solved. Also function signatures can exist
without lhs expr (anonymous function).
*/
- function_signature_resolve(nullable_unwrap(self->rhs_expr)->value.func_decl->signature, context);
+ function_signature_resolve(self->rhs_expr->value.func_decl->signature, context);
ast->resolve_data.status = AST_RESOLVED;
/*
If rhs is a function declaration then there is no need to wait until it has been resolved before setting the type as the type
@@ -462,9 +462,9 @@ static void import_resolve(Ast *ast, AstCompilerContext *context) {
static Scope* lhsexpr_get_scope(LhsExpr *self) {
AstValue value;
- if(is_not_null(self->rhs_expr)) {
- value = nullable_unwrap(self->rhs_expr)->value;
- switch(nullable_unwrap(self->rhs_expr)->type) {
+ if(self->rhs_expr) {
+ value = self->rhs_expr->value;
+ switch(self->rhs_expr->type) {
case AST_FUNCTION_DECL:
return &value.func_decl->body;
case AST_STRUCT_DECL:
@@ -497,7 +497,7 @@ static void funcdecl_resolve(FunctionDecl *self, AstCompilerContext *context) {
*/
bool resolved_type_is_func_decl(Ast *self) {
const LhsExpr *resolved_type = self->resolve_data.type;
- return (is_not_null(resolved_type->rhs_expr) && nullable_unwrap(resolved_type->rhs_expr)->type == AST_FUNCTION_DECL) ||
+ return (resolved_type->rhs_expr && resolved_type->rhs_expr->type == AST_FUNCTION_DECL) ||
resolved_type->type.type == VARIABLE_TYPE_SIGNATURE;
}
@@ -549,7 +549,7 @@ static void structfield_resolve(Ast *self, AstCompilerContext *context) {
static bool is_struct_decl(Ast *self) {
const LhsExpr *resolved_type = self->resolve_data.type;
assert(self->resolve_data.status == AST_RESOLVED);
- return is_not_null(resolved_type->rhs_expr) && nullable_unwrap(resolved_type->rhs_expr)->type == AST_STRUCT_DECL;
+ return resolved_type->rhs_expr && resolved_type->rhs_expr->type == AST_STRUCT_DECL;
}
static void binop_resolve_dot_access(Ast *ast, AstCompilerContext *context) {
diff --git a/src/bytecode/bytecode.c b/src/bytecode/bytecode.c
index d670407..70a5cfa 100644
--- a/src/bytecode/bytecode.c
+++ b/src/bytecode/bytecode.c
@@ -256,10 +256,10 @@ static const char* lhs_expr_get_c_name(BytecodeCompilerContext *self, LhsExpr *l
static void add_instructions(BytecodeCompilerContext *self) {
/*doc(Bytecode instructions)
# Instructions layout
- |Type |Field |Description |
- |------------|-----------------|---------------------------------------------------------------------------|
- |u32 |Instructions size|The size of the instructions section, in bytes. |
- |Instruction*|Instructions data|The instructions data. Each instructions begins with an opcode, see #Opcode|
+ |Type |Field |Description |
+ |-----------|-----------------|---------------------------------------------------------------------------|
+ |u32 |Instructions size|The size of the instructions section, in bytes. |
+ |Instruction|Instructions data|The instructions data. Each instructions begins with an opcode, see #Opcode|
*/
Ssa *ssa;
diff --git a/src/compiler.c b/src/compiler.c
index 524b555..8c3266c 100644
--- a/src/compiler.c
+++ b/src/compiler.c
@@ -34,7 +34,7 @@ static CHECK_RESULT int create_default_type(amal_compiler *compiler, const char
return_if_error(arena_allocator_alloc(&compiler->allocator, sizeof(LhsExpr), (void**)lhs_expr));
lhsexpr_init(*lhs_expr, bool_true, bool_true, bool_true, create_buffer_view(name, strnlen(name, PATH_MAX)));
- return_if_error(ast_create(&compiler->allocator, struct_decl, AST_STRUCT_DECL, &nullable_raw((*lhs_expr)->rhs_expr)));
+ return_if_error(ast_create(&compiler->allocator, struct_decl, AST_STRUCT_DECL, &(*lhs_expr)->rhs_expr));
return_if_error(ast_create(&compiler->allocator, *lhs_expr, AST_LHS, &expr));
expr->resolve_data.type = *lhs_expr;
expr->resolve_data.status = AST_RESOLVED;
diff --git a/src/nullable.c b/src/nullable.c
deleted file mode 100644
index df69148..0000000
--- a/src/nullable.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "../include/nullable.h"
-#include <assert.h>
-
-int assert_not_null(void *val) {
- (void)val;
- assert(val);
- return 1;
-}
diff --git a/src/parser.c b/src/parser.c
index 7d991a2..fdf34ce 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -62,7 +62,7 @@ int parser_init(Parser *self, amal_compiler *compiler, ArenaAllocator *allocator
return_if_error(structdecl_init(&self->struct_decl, &compiler->root_scope, allocator));
self->struct_decl.body.parser = self;
lhsexpr_init(&self->file_decl, bool_true, bool_true, bool_true, create_buffer_view_null());
- return_if_error(ast_create(self->allocator, &self->struct_decl, AST_STRUCT_DECL, &nullable_raw(self->file_decl.rhs_expr)));
+ return_if_error(ast_create(self->allocator, &self->struct_decl, AST_STRUCT_DECL, &self->file_decl.rhs_expr));
self->current_scope = &self->struct_decl.body;
self->has_func_parent = bool_false;
am_memset(&self->bytecode, 0, sizeof(self->bytecode));
@@ -667,21 +667,21 @@ Ast* parser_parse_body(Parser *self) {
func_decl = parser_parse_closure(self);
if(func_decl) {
- throw_if_error(ast_create(self->allocator, func_decl, AST_FUNCTION_DECL, &nullable_raw(lhs_expr->rhs_expr)));
+ throw_if_error(ast_create(self->allocator, func_decl, AST_FUNCTION_DECL, &lhs_expr->rhs_expr));
return result;
}
struct_decl = parser_parse_struct_decl(self);
if(struct_decl) {
- throw_if_error(ast_create(self->allocator, struct_decl, AST_STRUCT_DECL, &nullable_raw(lhs_expr->rhs_expr)));
+ throw_if_error(ast_create(self->allocator, struct_decl, AST_STRUCT_DECL, &lhs_expr->rhs_expr));
return result;
}
import = parser_parse_import(self);
if(import) {
parser_queue_file(self, import->path, &import->file_scope);
- throw_if_error(ast_create(self->allocator, import, AST_IMPORT, &nullable_raw(lhs_expr->rhs_expr)));
- parser_parse_body_semicolon(self, nullable_unwrap(lhs_expr->rhs_expr));
+ throw_if_error(ast_create(self->allocator, import, AST_IMPORT, &lhs_expr->rhs_expr));
+ parser_parse_body_semicolon(self, lhs_expr->rhs_expr);
return result;
}
} else {
@@ -696,7 +696,7 @@ Ast* parser_parse_body(Parser *self) {
self->error_context = ERROR_CONTEXT_NONE;
/* Variable declaration with lhs and rhs */
if(lhs_expr) {
- nullable_assign(lhs_expr->rhs_expr, rhs_expr);
+ lhs_expr->rhs_expr = rhs_expr;
} else {
bool match;
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_EQUALS, &match));
diff --git a/src/ssa/ssa.c b/src/ssa/ssa.c
index 405d8e4..707ccd0 100644
--- a/src/ssa/ssa.c
+++ b/src/ssa/ssa.c
@@ -342,8 +342,8 @@ static CHECK_RESULT SsaRegister lhsexpr_generate_ssa(Ast *self, SsaCompilerConte
if(lhs_expr->is_extern)
return lhsexpr_extern_generate_ssa(lhs_expr, context);
- if(is_not_null(lhs_expr->rhs_expr)) {
- Ast *rhs_expr = nullable_unwrap(lhs_expr->rhs_expr);
+ if(lhs_expr->rhs_expr) {
+ Ast *rhs_expr = lhs_expr->rhs_expr;
SsaRegister rhs_reg;
rhs_reg = ast_generate_ssa(rhs_expr, context);
/*
@@ -433,7 +433,7 @@ static CHECK_RESULT SsaRegister funccall_generate_ssa(Ast *self, SsaCompilerCont
throw_if_error(ssa_ins_push(context->ssa, arg_reg));
}
- assert((is_not_null(self->resolve_data.type->rhs_expr) && nullable_unwrap(self->resolve_data.type->rhs_expr)->type == AST_FUNCTION_DECL) ||
+ assert((self->resolve_data.type->rhs_expr && self->resolve_data.type->rhs_expr->type == AST_FUNCTION_DECL) ||
self->resolve_data.type->type.type == VARIABLE_TYPE_SIGNATURE);
if(self->resolve_data.type->is_extern) {
amal_log_error("TODO: Implement extern function call (extern function %.*s was called)", func_call->func.name.size, func_call->func.name.data);
@@ -442,7 +442,7 @@ static CHECK_RESULT SsaRegister funccall_generate_ssa(Ast *self, SsaCompilerCont
} else {
FunctionDecl *func_to_call;
/* rhs wont be null here because only extern variable can't have rhs */
- func_to_call = nullable_unwrap(self->resolve_data.type->rhs_expr)->value.func_decl;
+ func_to_call = self->resolve_data.type->rhs_expr->value.func_decl;
amal_log_debug("SSA funccall %.*s, func index ptr: %p", func_call->func.name.size, func_call->func.name.data, func_to_call);
throw_if_error(ssa_ins_call(context->ssa, func_to_call, &reg));
}
diff --git a/tests/bytecode.amal b/tests/bytecode.amal
index 3484b21..799733b 100644
--- a/tests/bytecode.amal
+++ b/tests/bytecode.amal
@@ -6,7 +6,7 @@ const main = fn {
const value2: i64 = 23;
const value3 = 2 + 5 - 1 * 10 / 2;
const str_value = "hello, world";
- printf();
+ //printf();
}
const print = fn {