mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 14:48:47 +00:00
f16/f128,u|i128, basic vector support.
This commit is contained in:
+162
-9
@@ -274,6 +274,22 @@ Type *check_type_expr_extra(Checker *c, AstNode *e, Type *named_type) {
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(vt, VectorType, e);
|
||||
Type *elem = check_type(c, vt->elem);
|
||||
Type *be = get_base_type(elem);
|
||||
if (!is_type_vector(be) &&
|
||||
!(is_type_boolean(be) || is_type_numeric(be))) {
|
||||
err_str = type_to_string(elem);
|
||||
error(&c->error_collector, ast_node_token(vt->elem), "Vector element type must be a boolean, numerical, or vector. Got `%s`", err_str);
|
||||
break;
|
||||
} else {
|
||||
i64 count = check_array_count(c, vt->count);
|
||||
Type *t = make_type_vector(c->allocator, elem, count);
|
||||
set_base_type(named_type, t);
|
||||
return t;
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(st, StructType, e);
|
||||
Type *t = make_type_structure(c->allocator);
|
||||
set_base_type(named_type, t);
|
||||
@@ -366,6 +382,22 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type) {
|
||||
goto end;
|
||||
case_end;
|
||||
|
||||
|
||||
case_ast_node(vt, VectorType, e);
|
||||
Type *elem = check_type(c, vt->elem);
|
||||
Type *be = get_base_type(elem);
|
||||
i64 count = check_array_count(c, vt->count);
|
||||
if (!is_type_vector(be) &&
|
||||
!(is_type_boolean(be) || is_type_numeric(be))) {
|
||||
err_str = type_to_string(elem);
|
||||
error(&c->error_collector, ast_node_token(vt->elem), "Vector element type must be a boolean, numerical, or vector. Got `%s`", err_str);
|
||||
} else {
|
||||
}
|
||||
type = make_type_vector(c->allocator, elem, count);
|
||||
set_base_type(named_type, type);
|
||||
goto end;
|
||||
case_end;
|
||||
|
||||
case_ast_node(st, StructType, e);
|
||||
type = make_type_structure(c->allocator);
|
||||
set_base_type(named_type, type);
|
||||
@@ -404,25 +436,26 @@ end:
|
||||
|
||||
b32 check_unary_op(Checker *c, Operand *o, Token op) {
|
||||
// TODO(bill): Handle errors correctly
|
||||
Type *type = get_base_type(base_vector_type(o->type));
|
||||
gbString str = NULL;
|
||||
defer (gb_string_free(str));
|
||||
switch (op.kind) {
|
||||
case Token_Add:
|
||||
case Token_Sub:
|
||||
if (!is_type_numeric(o->type)) {
|
||||
if (!is_type_numeric(type)) {
|
||||
str = expr_to_string(o->expr);
|
||||
error(&c->error_collector, op, "Operator `%.*s` is not allowed with `%s`", LIT(op.string), str);
|
||||
}
|
||||
break;
|
||||
|
||||
case Token_Xor:
|
||||
if (!is_type_integer(o->type)) {
|
||||
if (!is_type_integer(type)) {
|
||||
error(&c->error_collector, op, "Operator `%.*s` is only allowed with integers", LIT(op.string));
|
||||
}
|
||||
break;
|
||||
|
||||
case Token_Not:
|
||||
if (!is_type_boolean(o->type)) {
|
||||
if (!is_type_boolean(type)) {
|
||||
str = expr_to_string(o->expr);
|
||||
error(&c->error_collector, op, "Operator `%.*s` is only allowed on boolean expression", LIT(op.string));
|
||||
}
|
||||
@@ -438,6 +471,7 @@ b32 check_unary_op(Checker *c, Operand *o, Token op) {
|
||||
|
||||
b32 check_binary_op(Checker *c, Operand *o, Token op) {
|
||||
// TODO(bill): Handle errors correctly
|
||||
Type *type = get_base_type(base_vector_type(o->type));
|
||||
switch (op.kind) {
|
||||
case Token_Add:
|
||||
case Token_Sub:
|
||||
@@ -448,7 +482,7 @@ b32 check_binary_op(Checker *c, Operand *o, Token op) {
|
||||
case Token_SubEq:
|
||||
case Token_MulEq:
|
||||
case Token_QuoEq:
|
||||
if (!is_type_numeric(o->type)) {
|
||||
if (!is_type_numeric(type)) {
|
||||
error(&c->error_collector, op, "Operator `%.*s` is only allowed with numeric expressions", LIT(op.string));
|
||||
return false;
|
||||
}
|
||||
@@ -465,7 +499,7 @@ b32 check_binary_op(Checker *c, Operand *o, Token op) {
|
||||
case Token_OrEq:
|
||||
case Token_XorEq:
|
||||
case Token_AndNotEq:
|
||||
if (!is_type_integer(o->type)) {
|
||||
if (!is_type_integer(type)) {
|
||||
error(&c->error_collector, op, "Operator `%.*s` is only allowed with integers", LIT(op.string));
|
||||
return false;
|
||||
}
|
||||
@@ -476,7 +510,7 @@ b32 check_binary_op(Checker *c, Operand *o, Token op) {
|
||||
|
||||
case Token_CmpAndEq:
|
||||
case Token_CmpOrEq:
|
||||
if (!is_type_boolean(o->type)) {
|
||||
if (!is_type_boolean(type)) {
|
||||
error(&c->error_collector, op, "Operator `%.*s` is only allowed with boolean expressions", LIT(op.string));
|
||||
return false;
|
||||
}
|
||||
@@ -671,7 +705,107 @@ void check_comparison(Checker *c, Operand *x, Operand *y, Token op) {
|
||||
update_expr_type(c, y->expr, default_type(y->type), true);
|
||||
}
|
||||
|
||||
if (is_type_vector(x->type)) {
|
||||
Type *vec_bool = NULL;
|
||||
do {
|
||||
} while (is_type_vector(x->type->vector.elem));
|
||||
}
|
||||
x->type = t_untyped_bool;
|
||||
|
||||
}
|
||||
|
||||
void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) {
|
||||
GB_ASSERT(node->kind == AstNode_BinaryExpr);
|
||||
ast_node(be, BinaryExpr, node);
|
||||
|
||||
|
||||
ExactValue x_val = {};
|
||||
if (x->mode == Addressing_Constant) {
|
||||
x_val = exact_value_to_integer(x->value);
|
||||
}
|
||||
|
||||
b32 x_is_untyped = is_type_untyped(x->type);
|
||||
if (!(is_type_integer(x->type) || (x_is_untyped && x_val.kind == ExactValue_Integer))) {
|
||||
gbString err_str = expr_to_string(x->expr);
|
||||
defer (gb_string_free(err_str));
|
||||
error(&c->error_collector, ast_node_token(node),
|
||||
"Shifted operand `%s` must be an integer", err_str);
|
||||
x->mode = Addressing_Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_type_unsigned(y->type)) {
|
||||
|
||||
} else if (is_type_untyped(y->type)) {
|
||||
convert_to_typed(c, y, t_untyped_integer);
|
||||
if (y->mode == Addressing_Invalid) {
|
||||
x->mode = Addressing_Invalid;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
gbString err_str = expr_to_string(y->expr);
|
||||
defer (gb_string_free(err_str));
|
||||
error(&c->error_collector, ast_node_token(node),
|
||||
"Shift amount `%s` must be an unsigned integer", err_str);
|
||||
x->mode = Addressing_Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (x->mode == Addressing_Constant) {
|
||||
if (y->mode == Addressing_Constant) {
|
||||
ExactValue y_val = exact_value_to_integer(y->value);
|
||||
if (y_val.kind != ExactValue_Integer) {
|
||||
gbString err_str = expr_to_string(y->expr);
|
||||
defer (gb_string_free(err_str));
|
||||
error(&c->error_collector, ast_node_token(node),
|
||||
"Shift amount `%s` must be an unsigned integer", err_str);
|
||||
x->mode = Addressing_Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
u64 amount = cast(u64)y_val.value_integer;
|
||||
if (amount > 1074) {
|
||||
gbString err_str = expr_to_string(y->expr);
|
||||
defer (gb_string_free(err_str));
|
||||
error(&c->error_collector, ast_node_token(node),
|
||||
"Shift amount too large: `%s`", err_str);
|
||||
x->mode = Addressing_Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_type_integer(x->type)) {
|
||||
// NOTE(bill): It could be an untyped float but still representable
|
||||
// as an integer
|
||||
x->type = t_untyped_integer;
|
||||
}
|
||||
|
||||
x->value = exact_value_shift(be->op, x_val, make_exact_value_integer(amount));
|
||||
|
||||
if (is_type_typed(x->type)) {
|
||||
check_is_expressible(c, x, get_base_type(x->type));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (x_is_untyped) {
|
||||
ExpressionInfo *info = map_get(&c->info.untyped, hash_pointer(x->expr));
|
||||
if (info != NULL) {
|
||||
info->is_lhs = true;
|
||||
}
|
||||
x->mode = Addressing_Value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (y->mode == Addressing_Constant && y->value.value_integer < 0) {
|
||||
gbString err_str = expr_to_string(y->expr);
|
||||
defer (gb_string_free(err_str));
|
||||
error(&c->error_collector, ast_node_token(node),
|
||||
"Shift amount cannot be negative: `%s`", err_str);
|
||||
}
|
||||
|
||||
x->mode = Addressing_Value;
|
||||
}
|
||||
|
||||
void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
|
||||
@@ -684,13 +818,20 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
|
||||
|
||||
check_expr(c, x, be->left);
|
||||
check_expr(c, y, be->right);
|
||||
if (x->mode == Addressing_Invalid) return;
|
||||
if (x->mode == Addressing_Invalid) {
|
||||
return;
|
||||
}
|
||||
if (y->mode == Addressing_Invalid) {
|
||||
x->mode = Addressing_Invalid;
|
||||
x->expr = y->expr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (token_is_shift(be->op)) {
|
||||
check_shift(c, x, y, node);
|
||||
return;
|
||||
}
|
||||
|
||||
convert_to_typed(c, x, y->type);
|
||||
if (x->mode == Addressing_Invalid) return;
|
||||
convert_to_typed(c, y, x->type);
|
||||
@@ -791,8 +932,12 @@ void update_expr_type(Checker *c, AstNode *e, Type *type, b32 final) {
|
||||
if (found->value.kind != ExactValue_Invalid)
|
||||
break;
|
||||
if (!token_is_comparison(be->op)) {
|
||||
update_expr_type(c, be->left, type, final);
|
||||
update_expr_type(c, be->right, type, final);
|
||||
if (token_is_shift(be->op)) {
|
||||
update_expr_type(c, be->left, type, final);
|
||||
} else {
|
||||
update_expr_type(c, be->left, type, final);
|
||||
update_expr_type(c, be->right, type, final);
|
||||
}
|
||||
}
|
||||
case_end;
|
||||
}
|
||||
@@ -1891,6 +2036,7 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ
|
||||
case AstNode_ProcType:
|
||||
case AstNode_PointerType:
|
||||
case AstNode_ArrayType:
|
||||
case AstNode_VectorType:
|
||||
case AstNode_StructType:
|
||||
o->mode = Addressing_Type;
|
||||
o->type = check_type(c, node);
|
||||
@@ -2123,6 +2269,13 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
||||
str = write_expr_to_string(str, at->elem);
|
||||
case_end;
|
||||
|
||||
case_ast_node(vt, VectorType, node);
|
||||
str = gb_string_appendc(str, "{");
|
||||
str = write_expr_to_string(str, vt->count);
|
||||
str = gb_string_appendc(str, "}");
|
||||
str = write_expr_to_string(str, vt->elem);
|
||||
case_end;
|
||||
|
||||
case_ast_node(ce, CallExpr, node);
|
||||
str = write_expr_to_string(str, ce->proc);
|
||||
str = gb_string_appendc(str, "(");
|
||||
|
||||
+81
-14
@@ -7,12 +7,16 @@ enum BasicKind {
|
||||
Basic_i16,
|
||||
Basic_i32,
|
||||
Basic_i64,
|
||||
Basic_i128,
|
||||
Basic_u8,
|
||||
Basic_u16,
|
||||
Basic_u32,
|
||||
Basic_u64,
|
||||
Basic_u128,
|
||||
Basic_f16,
|
||||
Basic_f32,
|
||||
Basic_f64,
|
||||
Basic_f128,
|
||||
Basic_int,
|
||||
Basic_uint,
|
||||
Basic_rawptr,
|
||||
@@ -56,6 +60,7 @@ struct BasicType {
|
||||
TYPE_KIND(Invalid), \
|
||||
TYPE_KIND(Basic), \
|
||||
TYPE_KIND(Array), \
|
||||
TYPE_KIND(Vector), \
|
||||
TYPE_KIND(Slice), \
|
||||
TYPE_KIND(Structure), \
|
||||
TYPE_KIND(Pointer), \
|
||||
@@ -85,6 +90,10 @@ struct Type {
|
||||
Type *elem;
|
||||
i64 count;
|
||||
} array;
|
||||
struct {
|
||||
Type *elem;
|
||||
i64 count;
|
||||
} vector;
|
||||
struct {
|
||||
Type *elem;
|
||||
} slice;
|
||||
@@ -159,6 +168,13 @@ Type *make_type_array(gbAllocator a, Type *elem, i64 count) {
|
||||
return t;
|
||||
}
|
||||
|
||||
Type *make_type_vector(gbAllocator a, Type *elem, i64 count) {
|
||||
Type *t = alloc_type(a, Type_Vector);
|
||||
t->vector.elem = elem;
|
||||
t->vector.count = count;
|
||||
return t;
|
||||
}
|
||||
|
||||
Type *make_type_slice(gbAllocator a, Type *elem) {
|
||||
Type *t = alloc_type(a, Type_Slice);
|
||||
t->array.elem = elem;
|
||||
@@ -223,12 +239,16 @@ gb_global Type basic_types[] = {
|
||||
{Type_Basic, {Basic_i16, BasicFlag_Integer, STR_LIT("i16")}},
|
||||
{Type_Basic, {Basic_i32, BasicFlag_Integer, STR_LIT("i32")}},
|
||||
{Type_Basic, {Basic_i64, BasicFlag_Integer, STR_LIT("i64")}},
|
||||
{Type_Basic, {Basic_i128, BasicFlag_Integer, STR_LIT("i128")}},
|
||||
{Type_Basic, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u8")}},
|
||||
{Type_Basic, {Basic_u16, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u16")}},
|
||||
{Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u32")}},
|
||||
{Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u64")}},
|
||||
{Type_Basic, {Basic_u128, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u128")}},
|
||||
{Type_Basic, {Basic_f16, BasicFlag_Float, STR_LIT("f16")}},
|
||||
{Type_Basic, {Basic_f32, BasicFlag_Float, STR_LIT("f32")}},
|
||||
{Type_Basic, {Basic_f64, BasicFlag_Float, STR_LIT("f64")}},
|
||||
{Type_Basic, {Basic_f128, BasicFlag_Float, STR_LIT("f128")}},
|
||||
{Type_Basic, {Basic_int, BasicFlag_Integer, STR_LIT("int")}},
|
||||
{Type_Basic, {Basic_uint, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("uint")}},
|
||||
{Type_Basic, {Basic_rawptr, BasicFlag_Pointer, STR_LIT("rawptr")}},
|
||||
@@ -256,8 +276,10 @@ gb_global Type *t_u8 = &basic_types[Basic_u8];
|
||||
gb_global Type *t_u16 = &basic_types[Basic_u16];
|
||||
gb_global Type *t_u32 = &basic_types[Basic_u32];
|
||||
gb_global Type *t_u64 = &basic_types[Basic_u64];
|
||||
gb_global Type *t_f16 = &basic_types[Basic_f16];
|
||||
gb_global Type *t_f32 = &basic_types[Basic_f32];
|
||||
gb_global Type *t_f64 = &basic_types[Basic_f64];
|
||||
gb_global Type *t_f128 = &basic_types[Basic_f128];
|
||||
gb_global Type *t_int = &basic_types[Basic_int];
|
||||
gb_global Type *t_uint = &basic_types[Basic_uint];
|
||||
gb_global Type *t_rawptr = &basic_types[Basic_rawptr];
|
||||
@@ -295,6 +317,8 @@ b32 is_type_unsigned(Type *t) {
|
||||
b32 is_type_numeric(Type *t) {
|
||||
if (t->kind == Type_Basic)
|
||||
return (t->basic.flags & BasicFlag_Numeric) != 0;
|
||||
if (t->kind == Type_Vector)
|
||||
return is_type_numeric(t->vector.elem);
|
||||
return false;
|
||||
}
|
||||
b32 is_type_string(Type *t) {
|
||||
@@ -351,13 +375,22 @@ b32 is_type_u8(Type *t) {
|
||||
b32 is_type_slice(Type *t) {
|
||||
return t->kind == Type_Slice;
|
||||
}
|
||||
|
||||
|
||||
b32 is_type_u8_slice(Type *t) {
|
||||
if (t->kind == Type_Slice)
|
||||
return is_type_u8(t->slice.elem);
|
||||
return false;
|
||||
}
|
||||
b32 is_type_vector(Type *t) {
|
||||
return t->kind == Type_Vector;
|
||||
}
|
||||
Type *base_vector_type(Type *t) {
|
||||
while (is_type_vector(t)) {
|
||||
t = t->vector.elem;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
|
||||
b32 is_type_comparable(Type *t) {
|
||||
t = get_base_type(t);
|
||||
@@ -375,6 +408,8 @@ b32 is_type_comparable(Type *t) {
|
||||
} break;
|
||||
case Type_Array:
|
||||
return is_type_comparable(t->array.elem);
|
||||
case Type_Vector:
|
||||
return is_type_comparable(t->vector.elem);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -399,6 +434,11 @@ b32 are_types_identical(Type *x, Type *y) {
|
||||
return (x->array.count == y->array.count) && are_types_identical(x->array.elem, y->array.elem);
|
||||
break;
|
||||
|
||||
case Type_Vector:
|
||||
if (y->kind == Type_Vector)
|
||||
return (x->vector.count == y->vector.count) && are_types_identical(x->vector.elem, y->vector.elem);
|
||||
break;
|
||||
|
||||
case Type_Structure:
|
||||
if (y->kind == Type_Structure) {
|
||||
if (x->structure.field_count == y->structure.field_count) {
|
||||
@@ -482,18 +522,22 @@ struct BaseTypeSizes {
|
||||
|
||||
// TODO(bill): Change
|
||||
gb_global i64 basic_type_sizes[] = {
|
||||
0, // Basic_Invalid
|
||||
1, // Basic_bool // TODO(bill): What size should this be? And should I have different booleans?
|
||||
1, // Basic_i8
|
||||
2, // Basic_i16
|
||||
4, // Basic_i32
|
||||
8, // Basic_i64
|
||||
1, // Basic_u8
|
||||
2, // Basic_u16
|
||||
4, // Basic_u32
|
||||
8, // Basic_u64
|
||||
4, // Basic_f32
|
||||
8, // Basic_f64
|
||||
0, // Basic_Invalid
|
||||
1, // Basic_bool // TODO(bill): What size should this be? And should I have different booleans?
|
||||
1, // Basic_i8
|
||||
2, // Basic_i16
|
||||
4, // Basic_i32
|
||||
8, // Basic_i64
|
||||
16, // Basic_i128
|
||||
1, // Basic_u8
|
||||
2, // Basic_u16
|
||||
4, // Basic_u32
|
||||
8, // Basic_u64
|
||||
16, // Basic_u128
|
||||
2, // Basic_f16
|
||||
4, // Basic_f32
|
||||
8, // Basic_f64
|
||||
16, // Basic_f128
|
||||
};
|
||||
|
||||
|
||||
@@ -512,6 +556,12 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
||||
switch (t->kind) {
|
||||
case Type_Array:
|
||||
return type_align_of(s, allocator, t->array.elem);
|
||||
case Type_Vector: {
|
||||
i64 size = type_size_of(s, allocator, t->vector.elem);
|
||||
// TODO(bill): Type_Vector type_align_of
|
||||
return gb_clamp(size, 1, 2*s.max_align);
|
||||
} break;
|
||||
|
||||
case Type_Structure: {
|
||||
i64 max = 1;
|
||||
for (isize i = 0; i < t->structure.field_count; i++) {
|
||||
@@ -575,6 +625,18 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
||||
return alignment*(count-1) + size;
|
||||
} break;
|
||||
|
||||
case Type_Vector: {
|
||||
i64 count = t->vector.count;
|
||||
if (count == 0)
|
||||
return 0;
|
||||
count = next_pow2(count);
|
||||
i64 align = type_align_of(s, allocator, t->vector.elem);
|
||||
i64 size = type_size_of(s, allocator, t->vector.elem);
|
||||
i64 alignment = align_formula(size, align);
|
||||
return alignment*(count-1) + size;
|
||||
} break;
|
||||
|
||||
|
||||
case Type_Slice: // ptr + len + cap
|
||||
return 3 * s.word_size;
|
||||
|
||||
@@ -617,6 +679,11 @@ gbString write_type_to_string(gbString str, Type *type) {
|
||||
str = write_type_to_string(str, type->array.elem);
|
||||
break;
|
||||
|
||||
case Type_Vector:
|
||||
str = gb_string_appendc(str, gb_bprintf("{%td}", type->vector.count));
|
||||
str = write_type_to_string(str, type->vector.elem);
|
||||
break;
|
||||
|
||||
case Type_Slice:
|
||||
str = gb_string_appendc(str, "[]");
|
||||
str = write_type_to_string(str, type->array.elem);
|
||||
|
||||
Reference in New Issue
Block a user