Skip to content

Commit

Permalink
CSmith helps
Browse files Browse the repository at this point in the history
  • Loading branch information
RealNeGate committed Jan 18, 2025
1 parent 7311104 commit 5c6f6ef
Show file tree
Hide file tree
Showing 37 changed files with 6,294 additions and 731 deletions.
28 changes: 27 additions & 1 deletion common/arena_array.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,38 @@ static void* aarray__reserve(void* ptr, size_t type_size, size_t min_size) {
return ptr;
}

static void* aarray__reserve2(void* ptr, size_t type_size, size_t min_size) {
AArray* header = ((AArray*)ptr) - 1;

if (min_size >= header->capacity) {
size_t old = header->capacity;
header->capacity = min_size * 2;

AArray* new_ptr = tb_arena_realloc(header->arena, header, sizeof(AArray) + (type_size * old), sizeof(AArray) + (type_size * header->capacity));
if (!new_ptr) {
fprintf(stderr, "error: out of memory!");
abort();
}

ptr = &new_ptr->data[0];
header = new_ptr;
}

// zero out the space up to the min_size
if (min_size > header->length) {
memset(&header->data[header->length * type_size], 0, (min_size - header->length) * type_size);
}
header->length = min_size + 1;

return ptr;
}

#define ArenaArray(T) T*
#define aarray_create(arena, T, cap) (T*) aarray__create(arena, sizeof(T), cap)
#define aarray_length(arr) ((((AArray*) (arr)) - 1)->length)
#define aarray_set_length(arr, len) ((((AArray*) (arr)) - 1)->length = (len))
#define aarray_clear(arr) ((((AArray*) (arr)) - 1)->length = 0)
#define aarray_insert(arr, i, ...) ((arr) = aarray__reserve(arr, sizeof(*(arr)), (i)), (arr)[i] = __VA_ARGS__)
#define aarray_insert(arr, i, ...) ((arr) = aarray__reserve2(arr, sizeof(*(arr)), (i)), (arr)[i] = __VA_ARGS__)
#define aarray_push(arr, ...) ((arr) = aarray__reserve(arr, sizeof(*(arr)), aarray_length(arr)), (arr)[aarray_length(arr)++] = __VA_ARGS__)
#define aarray_pop(arr) ((arr)[(((AArray*)(arr)) - 1)->length -= 1])
#define aarray_top(arr) ((arr)[(((AArray*)(arr)) - 1)->length - 1])
Expand Down
162 changes: 97 additions & 65 deletions cuik_c/expr_fold.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@
#define GET_CONST_INT(e) (e.i)
#define SET_CONST_INT(lhs, rhs) (lhs.tag = CUIK_CONST_INT, lhs.i = (rhs))

static bool const_eval(Cuik_Parser* restrict parser, Cuik_Expr* e, Cuik_ConstVal* out_val);
static bool const_eval(Cuik_Parser* restrict parser, TokenStream* tokens, Cuik_Expr* e, Cuik_ConstVal* out_val);

enum { CONST_ERROR = -2 };

// -1 for error
static ptrdiff_t const_eval_subexpr(Cuik_Parser* restrict parser, Cuik_QualType* types, Subexpr* exprs, ptrdiff_t i, Cuik_ConstVal* res) {
static ptrdiff_t const_eval_subexpr(Cuik_Parser* restrict parser, TokenStream* tokens, Cuik_QualType* types, Subexpr* exprs, ptrdiff_t i, Cuik_ConstVal* res) {
assert(i >= 0);
Subexpr* s = &exprs[i];

Expand All @@ -31,11 +30,11 @@ static ptrdiff_t const_eval_subexpr(Cuik_Parser* restrict parser, Cuik_QualType*
case EXPR_SIZEOF_T: {
Cuik_Type* src = cuik_canonical_type(s->x_of_type.type);
if (src->size == 0) {
type_layout2(parser, &parser->tokens, src);
type_layout2(parser, tokens, src);

if (src->size == 0) {
diag_err(&parser->tokens, s->loc, "Could not resolve type");
return -1;
diag_err(tokens, s->loc, "Could not resolve type");
return CONST_ERROR;
}
}

Expand All @@ -45,7 +44,7 @@ static ptrdiff_t const_eval_subexpr(Cuik_Parser* restrict parser, Cuik_QualType*

case EXPR_ENUM: {
if (s->enum_val.num->lexer_pos != 0) {
type_layout2(parser, &parser->tokens, cuik_canonical_type(s->enum_val.type));
type_layout2(parser, tokens, cuik_canonical_type(s->enum_val.type));
}

*res = (Cuik_ConstVal){ CUIK_CONST_INT, .i = s->enum_val.num->value };
Expand All @@ -54,7 +53,7 @@ static ptrdiff_t const_eval_subexpr(Cuik_Parser* restrict parser, Cuik_QualType*
case EXPR_CAST: {
Cuik_ConstVal src;

i = const_eval_subexpr(parser, types, exprs, i - 1, &src);
i = const_eval_subexpr(parser, tokens, types, exprs, i - 1, &src);
if (i == CONST_ERROR) return i;

assert(src.tag == CUIK_CONST_INT);
Expand All @@ -65,75 +64,109 @@ static ptrdiff_t const_eval_subexpr(Cuik_Parser* restrict parser, Cuik_QualType*
i -= 1;

// find base (just skip arrow or dot)
Subexpr* base = &exprs[i];
if (base->op == EXPR_DOT || base->op == EXPR_ARROW) {
base -= 1;
}
/* if (exprs[i].op == EXPR_DOT || exprs[i].op == EXPR_ARROW) {
i -= 1;
} */

Cuik_Type* t = NULL;
if (base->op == EXPR_CAST) {
t = cuik_canonical_type(base->cast.type);
base -= 1;
if (base->op == EXPR_INT) {
// (T*) 0
*res = (Cuik_ConstVal){ CUIK_CONST_INT, .i = base->int_lit.lit };
} else if (base->op == EXPR_SYMBOL) {
*res = (Cuik_ConstVal){ CUIK_CONST_ADDR, .s = { base - exprs, 0 } };
} else {
diag_err(&parser->tokens, s->loc, "Cannot evaluate address as constant");
return CONST_ERROR;
}
if (exprs[i].op == EXPR_CAST) {
t = cuik_canonical_type(exprs[i].cast.type);
i -= 1;
}

ptrdiff_t offset = 0;
Subexpr* s = &exprs[i];
if (s->op == EXPR_ARROW) {
// &(a->b) A -> &
if (t == NULL) {
diag_err(&parser->tokens, s->loc, "Unknown type, cannot get member: %s", s->dot_arrow.name);
return CONST_ERROR;
}
while (exprs[i].op == EXPR_ARROW || exprs[i].op == EXPR_DOT_R || exprs[i].op == EXPR_SUBSCRIPT) {
Subexpr* s = &exprs[i];

if (exprs[i].op == EXPR_DOT_R) {
offset += exprs[i].dot_arrow.offset;
i -= 1;
} else if (exprs[i].op == EXPR_ARROW) {
// &(a->b) A -> &
if (t == NULL) {
diag_err(tokens, s->loc, "Unknown type, cannot get member: %s", s->dot_arrow.name);
return CONST_ERROR;
}

if (cuik_type_can_deref(t)) {
t = cuik_canonical_type(t->ptr_to);
} else {
diag_err(&parser->tokens, s->loc, "Expected pointer (or array) for arrow");
return CONST_ERROR;
}
if (cuik_type_can_deref(t)) {
t = cuik_canonical_type(t->ptr_to);
} else {
diag_err(tokens, s->loc, "Expected pointer (or array) for arrow");
return CONST_ERROR;
}

// force this expression's type to resolve
if (t->size == 0) {
type_layout2(parser, &parser->tokens, t);
}
// force this expression's type to resolve
if (t->size == 0) {
type_layout2(parser, tokens, t);
}

uint32_t member_offset = 0;
Member* member = sema_traverse_members(t, s->dot_arrow.name, &member_offset);
if (member == NULL) {
diag_err(tokens, s->loc, "Unknown member: %s", s->dot_arrow.name);
return CONST_ERROR;
}

offset += member_offset;
i -= 1;
} else if (exprs[i].op == EXPR_SUBSCRIPT) {
t = cuik_canonical_type(types[i]);

if (t == NULL) {
diag_err(tokens, s->loc, "Unknown type, cannot get member: %s", s->dot_arrow.name);
return CONST_ERROR;
}

// force this expression's type to resolve
if (t->size == 0) {
type_layout2(parser, tokens, t);
}

Cuik_ConstVal idx;
i = const_eval_subexpr(parser, tokens, types, exprs, i - 1, &idx);
if (i == CONST_ERROR) return i;

if (idx.tag != CUIK_CONST_INT) {
diag_err(tokens, s->loc, "Array index wasn't an integer");
return CONST_ERROR;
}

uint32_t member_offset = 0;
Member* member = sema_traverse_members(t, s->dot_arrow.name, &member_offset);
if (member == NULL) {
diag_err(&parser->tokens, s->loc, "Unknown member: %s", s->dot_arrow.name);
offset += idx.i * t->size;
} else {
diag_err(tokens, s->loc, "TODO");
return CONST_ERROR;
}
}

offset += member_offset;
i -= 1;
if (exprs[i].op == EXPR_INT) {
// (T*) 0
*res = (Cuik_ConstVal){ CUIK_CONST_INT, .i = exprs[i].int_lit.lit };
} else if (exprs[i].op == EXPR_SYMBOL) {
*res = (Cuik_ConstVal){ CUIK_CONST_ADDR, .s = { exprs[i].sym.stmt, 0 } };
} else {
diag_err(tokens, s->loc, "Cannot evaluate address as constant");
return CONST_ERROR;
}

if (res->tag == CUIK_CONST_ADDR) {
res->s.offset += offset;
} else {
assert(res->tag == CUIK_CONST_INT);
} else if (res->tag == CUIK_CONST_INT) {
res->i += offset;
} else {
diag_err(tokens, s->loc, "Cannot evaluate address as constant");
return CONST_ERROR;
}

return (base - exprs) - 1;
return i - 1;
}
case EXPR_SYMBOL: {
Stmt* sym = s->sym.stmt;
if (!cuik_type_implicit_ptr(cuik_canonical_type(sym->decl.type))) {
diag_err(&parser->tokens, s->loc, "Cannot evaluate address as constant");
diag_err(tokens, s->loc, "Cannot evaluate address as constant");
return CONST_ERROR;
}

*res = (Cuik_ConstVal){ CUIK_CONST_ADDR, .s = { i, 0 } };
*res = (Cuik_ConstVal){ CUIK_CONST_ADDR, .s = { exprs[i].sym.stmt, 0 } };
return i - 1;
}
default: break;
Expand All @@ -142,11 +175,11 @@ static ptrdiff_t const_eval_subexpr(Cuik_Parser* restrict parser, Cuik_QualType*
// try unary operators
if (s->op == EXPR_NOT || s->op == EXPR_NEGATE) {
Cuik_ConstVal src;
Cuik_Type* ty = types ? cuik_canonical_type(types[i - 1]) : NULL;

i = const_eval_subexpr(parser, types, exprs, i - 1, &src);
i = const_eval_subexpr(parser, tokens, types, exprs, i - 1, &src);
if (i == CONST_ERROR) return i;

Cuik_Type* ty = types ? cuik_canonical_type(types[i]) : NULL;
if (ty && cuik_type_is_float(ty)) {
assert(s->op == EXPR_NEGATE && "expected negate");

Expand All @@ -170,9 +203,9 @@ static ptrdiff_t const_eval_subexpr(Cuik_Parser* restrict parser, Cuik_QualType*
if (s->op >= EXPR_PLUS && s->op <= EXPR_CMPLT) {
Cuik_ConstVal rhs, lhs;

i = const_eval_subexpr(parser, types, exprs, i - 1, &rhs);
i = const_eval_subexpr(parser, tokens, types, exprs, i - 1, &rhs);
if (i == CONST_ERROR) return i;
i = const_eval_subexpr(parser, types, exprs, i, &lhs);
i = const_eval_subexpr(parser, tokens, types, exprs, i, &lhs);
if (i == CONST_ERROR) return i;

Cuik_Type* ty = types ? cuik_canonical_type(types[i]) : NULL;
Expand Down Expand Up @@ -229,25 +262,25 @@ static ptrdiff_t const_eval_subexpr(Cuik_Parser* restrict parser, Cuik_QualType*

if (s->op == EXPR_TERNARY) {
Cuik_ConstVal src;
i = const_eval_subexpr(parser, types, exprs, i - 1, &src);
i = const_eval_subexpr(parser, tokens, types, exprs, i - 1, &src);
if (i == CONST_ERROR) return i;

if (src.tag != CUIK_CONST_INT) {
diag_err(&parser->tokens, s->loc, "Ternary condition must be int");
diag_err(tokens, s->loc, "Ternary condition must be int");
return CONST_ERROR;
}

Cuik_ConstVal v;
if (!const_eval(parser, src.i ? s->ternary.left : s->ternary.right, &v)) {
diag_err(&parser->tokens, s->loc, "Cannot fold ternary");
if (!const_eval(parser, tokens, src.i ? s->ternary.left : s->ternary.right, &v)) {
diag_err(tokens, s->loc, "Cannot fold ternary");
return CONST_ERROR;
}

*res = v;
return i;
}

diag_err(parser ? &parser->tokens : NULL, s->loc, "could not parse subexpression '%s' as constant.", cuik_get_expr_name(s));
diag_err(tokens, s->loc, "could not parse subexpression '%s' as constant.", cuik_get_expr_name(s));
return CONST_ERROR;
}

Expand Down Expand Up @@ -277,8 +310,7 @@ static bool const_eval_addr_single(Cuik_Parser* restrict parser, Cuik_Expr* e, S
return false;
}

Subexpr* s = &e->exprs[args[0].s.base];
Stmt* sym = s->sym.stmt;
Stmt* sym = args[0].s.base;
if (cuik_canonical_type(sym->decl.type)->size == 0) {
type_layout2(parser, &parser->tokens, cuik_canonical_type(sym->decl.type));

Expand Down Expand Up @@ -308,8 +340,8 @@ static bool const_eval_addr_single(Cuik_Parser* restrict parser, Cuik_Expr* e, S
}

// does constant eval on integer values, if it ever fails it'll exit with false
static bool const_eval(Cuik_Parser* restrict parser, Cuik_Expr* e, Cuik_ConstVal* out_val) {
return const_eval_subexpr(parser, e->types, e->exprs, e->count - 1, out_val) != CONST_ERROR;
static bool const_eval(Cuik_Parser* restrict parser, TokenStream* tokens, Cuik_Expr* e, Cuik_ConstVal* out_val) {
return const_eval_subexpr(parser, tokens, e->types, e->exprs, e->count - 1, out_val) != CONST_ERROR;

#if 0
size_t top = 0;
Expand Down
2 changes: 1 addition & 1 deletion cuik_c/expr_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1096,7 +1096,7 @@ static intmax_t parse_const_expr(Cuik_Parser* parser, TokenStream* restrict s) {
Cuik_Expr* e = complete_expr(parser);

Cuik_ConstVal value;
if (!const_eval(parser, e, &value)) {
if (!const_eval(parser, &parser->tokens, e, &value)) {
// the const_eval_int will handle errors
return 0;
}
Expand Down
Loading

0 comments on commit 5c6f6ef

Please sign in to comment.