aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-06-03 22:27:23 +0100
committerGinger Bill <bill@gingerbill.org>2017-06-03 22:27:23 +0100
commit2c0e59ae064b273899a56cb8d3c53b6967466fa2 (patch)
tree0e1a9dc2ac94b7dfc408166f1cc1e0b921a5aba3 /src
parent9d1a4c304a27c0b762809bc3c1d6c70fdb5137be (diff)
`bit_field`; Lexical sugar operators ≠ ≤ ≥
Example below: // See: https://en.wikipedia.org/wiki/Bit_field BoxProps :: bit_field { opaque : 1, fill_colour : 3, _ : 4, show_border : 1, border_colour : 3, border_style : 2, _ : 2, width : 4, height : 4, _ : 8, }
Diffstat (limited to 'src')
-rw-r--r--src/check_decl.c4
-rw-r--r--src/check_expr.c140
-rw-r--r--src/check_stmt.c37
-rw-r--r--src/checker.c33
-rw-r--r--src/entity.c23
-rw-r--r--src/ir.c291
-rw-r--r--src/ir_print.c19
-rw-r--r--src/parser.c63
-rw-r--r--src/ssa.c2
-rw-r--r--src/tokenizer.c5
-rw-r--r--src/types.c141
11 files changed, 681 insertions, 77 deletions
diff --git a/src/check_decl.c b/src/check_decl.c
index 6b15cdaca..a14c79a20 100644
--- a/src/check_decl.c
+++ b/src/check_decl.c
@@ -40,6 +40,10 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
}
t = default_type(t);
}
+ if (is_type_bit_field_value(t)) {
+ t = default_bit_field_value_type(t);
+ }
+
GB_ASSERT(is_type_typed(t));
e->type = t;
}
diff --git a/src/check_expr.c b/src/check_expr.c
index 468598caf..9b23e57e4 100644
--- a/src/check_expr.c
+++ b/src/check_expr.c
@@ -192,6 +192,18 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) {
return 1;
}
+
+ if (is_type_bit_field_value(operand->type) && is_type_integer(type)) {
+ Type *bfv = base_type(operand->type);
+ i32 bits = bfv->BitFieldValue.bits;
+ i32 size = next_pow2((bits+7)/8);
+ i32 dst_size = type_size_of(c->allocator, type);
+ i32 diff = gb_abs(dst_size - size);
+ // TODO(bill): figure out a decent rule here
+ return 1;
+ }
+
+
if (check_is_assignable_to_using_subtype(operand->type, type)) {
return 4;
}
@@ -301,10 +313,10 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n
}
}
-
if (type == NULL) {
return;
}
+
if (!check_is_assignable_to(c, operand, type)) {
gbString type_str = type_to_string(type);
gbString op_type_str = type_to_string(operand->type);
@@ -901,6 +913,119 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
}
+void check_bit_field_type(Checker *c, Type *bit_field_type, Type *named_type, AstNode *node) {
+ ast_node(bft, BitFieldType, node);
+ GB_ASSERT(is_type_bit_field(bit_field_type));
+
+ gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
+
+
+ MapEntity entity_map = {0}; // Key: String
+ map_entity_init_with_reserve(&entity_map, c->tmp_allocator, 2*(bft->fields.count));
+
+ isize field_count = 0;
+ Entity **fields = gb_alloc_array(c->allocator, Entity *, bft->fields.count);
+ u32 * sizes = gb_alloc_array(c->allocator, u32, bft->fields.count);
+ u32 * offsets = gb_alloc_array(c->allocator, u32, bft->fields.count);
+
+ u32 curr_offset = 0;
+ for_array(i, bft->fields) {
+ AstNode *field = bft->fields.e[i];
+ GB_ASSERT(field->kind == AstNode_FieldValue);
+ AstNode *ident = field->FieldValue.field;
+ AstNode *value = field->FieldValue.value;
+
+ if (ident->kind != AstNode_Ident) {
+ error_node(field, "A bit field value's name must be an identifier");
+ continue;
+ }
+ String name = ident->Ident.string;
+
+ Operand o = {0};
+ check_expr(c, &o, value);
+ if (o.mode != Addressing_Constant) {
+ error_node(value, "Bit field bit size must be a constant");
+ continue;
+ }
+ ExactValue v = exact_value_to_integer(o.value);
+ if (v.kind != ExactValue_Integer) {
+ error_node(value, "Bit field bit size must be a constant integer");
+ continue;
+ }
+ i64 bits = i128_to_i64(v.value_integer);
+ if (bits < 0 || bits > 128) {
+ error_node(value, "Bit field's bit size must be within the range 1..<128, got %lld", cast(long long)bits);
+ continue;
+ }
+
+ Type *value_type = make_type_bit_field_value(c->allocator, bits);
+ Entity *e = make_entity_variable(c->allocator, bit_field_type->BitField.scope, ident->Ident, value_type, false);
+ e->identifier = ident;
+ e->flags |= EntityFlag_BitFieldValue;
+
+ HashKey key = hash_string(name);
+ if (str_ne(name, str_lit("_")) &&
+ map_entity_get(&entity_map, key) != NULL) {
+ error_node(ident, "`%.*s` is already declared in this bit field", LIT(name));
+ } else {
+ map_entity_set(&entity_map, key, e);
+ add_entity(c, c->context.scope, NULL, e);
+ add_entity_use(c, field, e);
+
+ fields [field_count] = e;
+ offsets[field_count] = curr_offset;
+ sizes [field_count] = bits;
+ field_count++;
+
+ curr_offset += bits;
+ }
+ }
+ GB_ASSERT(field_count <= bft->fields.count);
+ gb_temp_arena_memory_end(tmp);
+
+ bit_field_type->BitField.fields = fields;
+ bit_field_type->BitField.field_count = field_count;
+ bit_field_type->BitField.sizes = sizes;
+ bit_field_type->BitField.offsets = offsets;
+
+
+ if (bft->align != NULL) {
+ Operand o = {0};
+ check_expr(c, &o, bft->align);
+ if (o.mode != Addressing_Constant) {
+ if (o.mode != Addressing_Invalid) {
+ error_node(bft->align, "#align must be a constant");
+ }
+ return;
+ }
+
+ Type *type = base_type(o.type);
+ if (is_type_untyped(type) || is_type_integer(type)) {
+ if (o.value.kind == ExactValue_Integer) {
+ i64 align = i128_to_i64(o.value.value_integer);
+ if (align < 1 || !gb_is_power_of_two(align)) {
+ error_node(bft->align, "#align must be a power of 2, got %lld", align);
+ return;
+ }
+
+ // NOTE(bill): Success!!!
+ i64 custom_align = gb_clamp(align, 1, build_context.max_align);
+ if (custom_align < align) {
+ warning_node(bft->align, "Custom alignment has been clamped to %lld from %lld", align, custom_align);
+ }
+ bit_field_type->BitField.custom_align = custom_align;
+ return;
+ }
+ }
+
+ error_node(bft->align, "#align must be an integer");
+ return;
+ }
+}
+
+
+
+
Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_variadic_) {
if (_params == NULL) {
return NULL;
@@ -1766,6 +1891,15 @@ bool check_type_extra_internal(Checker *c, AstNode *e, Type **type, Type *named_
return true;
case_end;
+ case_ast_node(et, BitFieldType, e);
+ *type = make_type_bit_field(c->allocator);
+ set_base_type(named_type, *type);
+ check_open_scope(c, e);
+ check_bit_field_type(c, *type, named_type, e);
+ check_close_scope(c);
+ return true;
+ case_end;
+
case_ast_node(pt, ProcType, e);
*type = alloc_type(c->allocator, Type_Proc);
set_base_type(named_type, *type);
@@ -1985,7 +2119,7 @@ bool check_representable_as_constant(Checker *c, ExactValue in_value, Type *type
if (s < 128) {
umax = u128_sub(u128_shl(U128_ONE, s), U128_ONE);
} else {
- // IMPORTANT TODO(bill): I NEED A PROPER BIG NUMBER LIBRARY THAT CAN SUPPORT 128 bit integers and floats
+ // IMPORTANT TODO(bill): I NEED A PROPER BIG NUMBER LIBRARY THAT CAN SUPPORT 128 bit floats
s = 128;
}
i128 imax = i128_shl(I128_ONE, s-1ll);
@@ -2021,6 +2155,7 @@ bool check_representable_as_constant(Checker *c, ExactValue in_value, Type *type
switch (type->Basic.kind) {
+ // case Basic_f16:
case Basic_f32:
case Basic_f64:
return true;
@@ -4080,6 +4215,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
BasicKind kind = core_type(x.type)->Basic.kind;
switch (kind) {
+ // case Basic_f16: operand->type = t_complex32; break;
case Basic_f32: operand->type = t_complex64; break;
case Basic_f64: operand->type = t_complex128; break;
case Basic_UntypedFloat: operand->type = t_untyped_complex; break;
diff --git a/src/check_stmt.c b/src/check_stmt.c
index e00ba4bc1..d9639a11e 100644
--- a/src/check_stmt.c
+++ b/src/check_stmt.c
@@ -207,7 +207,6 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
return NULL;
}
-
if (rhs->mode == Addressing_Overload) {
isize overload_count = rhs->overload_count;
Entity **procs = rhs->overload_entities;
@@ -256,8 +255,42 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
case Addressing_Invalid:
return NULL;
- case Addressing_Variable:
+ case Addressing_Variable: {
+ if (is_type_bit_field_value(lhs.type)) {
+ Type *lt = base_type(lhs.type);
+ i64 lhs_bits = lt->BitFieldValue.bits;
+ if (rhs->mode == Addressing_Constant) {
+ ExactValue v = exact_value_to_integer(rhs->value);
+ if (v.kind == ExactValue_Integer) {
+ i128 i = v.value_integer;
+ u128 u = *cast(u128 *)&i;
+ u128 umax = U128_NEG_ONE;
+ if (lhs_bits < 128) {
+ umax = u128_sub(u128_shl(U128_ONE, lhs_bits), U128_ONE);
+ }
+ i128 imax = i128_shl(I128_ONE, lhs_bits-1ll);
+
+ bool ok = false;
+ ok = !(u128_lt(u, U128_ZERO) || u128_gt(u, umax));
+
+ if (ok) {
+ return rhs->type;
+ }
+ }
+ } else if (is_type_integer(rhs->type)) {
+ // TODO(bill): Any other checks?
+ return rhs->type;
+ }
+ gbString lhs_expr = expr_to_string(lhs.expr);
+ gbString rhs_expr = expr_to_string(rhs->expr);
+ error_node(rhs->expr, "Cannot assign `%s` to bit field `%s`", rhs_expr, lhs_expr);
+ gb_string_free(rhs_expr);
+ gb_string_free(lhs_expr);
+ return NULL;
+ }
break;
+ }
+
case Addressing_MapIndex: {
AstNode *ln = unparen_expr(lhs_node);
if (ln->kind == AstNode_IndexExpr) {
diff --git a/src/checker.c b/src/checker.c
index 47842d913..a7f8ec950 100644
--- a/src/checker.c
+++ b/src/checker.c
@@ -126,19 +126,19 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
#include "types.c"
typedef enum AddressingMode {
- Addressing_Invalid, // invalid addressing mode
- Addressing_NoValue, // no value (void in C)
- Addressing_Value, // computed value (rvalue)
- Addressing_Immutable, // immutable computed value (const rvalue)
- Addressing_Variable, // addressable variable (lvalue)
- Addressing_Constant, // constant
- Addressing_Type, // type
- Addressing_Builtin, // built-in procedure
- Addressing_Overload, // overloaded procedure
- Addressing_MapIndex, // map index expression -
- // lhs: acts like a Variable
- // rhs: acts like OptionalOk
- Addressing_OptionalOk, // rhs: acts like a value with an optional boolean part (for existence check)
+ Addressing_Invalid, // invalid addressing mode
+ Addressing_NoValue, // no value (void in C)
+ Addressing_Value, // computed value (rvalue)
+ Addressing_Immutable, // immutable computed value (const rvalue)
+ Addressing_Variable, // addressable variable (lvalue)
+ Addressing_Constant, // constant
+ Addressing_Type, // type
+ Addressing_Builtin, // built-in procedure
+ Addressing_Overload, // overloaded procedure
+ Addressing_MapIndex, // map index expression -
+ // lhs: acts like a Variable
+ // rhs: acts like OptionalOk
+ Addressing_OptionalOk, // rhs: acts like a value with an optional boolean part (for existence check)
} AddressingMode;
// Operand is used as an intermediate value whilst checking
@@ -947,6 +947,9 @@ void add_type_info_type(Checker *c, Type *t) {
return;
}
t = default_type(t);
+ if (is_type_bit_field_value(t)) {
+ t = default_bit_field_value_type(t);
+ }
if (is_type_untyped(t)) {
return; // Could be nil
}
@@ -1200,7 +1203,7 @@ void init_preload(Checker *c) {
- if (record->variant_count != 21) {
+ if (record->variant_count != 22) {
compiler_error("Invalid `TypeInfo` layout");
}
t_type_info_named = record->variants[ 1]->type;
@@ -1223,6 +1226,7 @@ void init_preload(Checker *c) {
t_type_info_union = record->variants[18]->type;
t_type_info_enum = record->variants[19]->type;
t_type_info_map = record->variants[20]->type;
+ t_type_info_bit_field = record->variants[21]->type;
t_type_info_named_ptr = make_type_pointer(c->allocator, t_type_info_named);
t_type_info_integer_ptr = make_type_pointer(c->allocator, t_type_info_integer);
@@ -1244,6 +1248,7 @@ void init_preload(Checker *c) {
t_type_info_union_ptr = make_type_pointer(c->allocator, t_type_info_union);
t_type_info_enum_ptr = make_type_pointer(c->allocator, t_type_info_enum);
t_type_info_map_ptr = make_type_pointer(c->allocator, t_type_info_map);
+ t_type_info_bit_field_ptr = make_type_pointer(c->allocator, t_type_info_bit_field);
}
if (t_allocator == NULL) {
diff --git a/src/entity.c b/src/entity.c
index ddc170597..f029685c3 100644
--- a/src/entity.c
+++ b/src/entity.c
@@ -33,17 +33,18 @@ String const entity_strings[] = {
};
typedef enum EntityFlag {
- EntityFlag_Visited = 1<<0,
- EntityFlag_Used = 1<<1,
- EntityFlag_Using = 1<<2,
- EntityFlag_Field = 1<<3,
- EntityFlag_Param = 1<<4,
- EntityFlag_VectorElem = 1<<5,
- EntityFlag_Ellipsis = 1<<6,
- EntityFlag_NoAlias = 1<<7,
- EntityFlag_TypeField = 1<<8,
- EntityFlag_Value = 1<<9,
- EntityFlag_Sret = 1<<10,
+ EntityFlag_Visited = 1<<0,
+ EntityFlag_Used = 1<<1,
+ EntityFlag_Using = 1<<2,
+ EntityFlag_Field = 1<<3,
+ EntityFlag_Param = 1<<4,
+ EntityFlag_VectorElem = 1<<5,
+ EntityFlag_Ellipsis = 1<<6,
+ EntityFlag_NoAlias = 1<<7,
+ EntityFlag_TypeField = 1<<8,
+ EntityFlag_Value = 1<<9,
+ EntityFlag_Sret = 1<<10,
+ EntityFlag_BitFieldValue = 1<<11,
} EntityFlag;
// Zero value means the overloading process is not yet done
diff --git a/src/ir.c b/src/ir.c
index 8864e1c45..10d744f20 100644
--- a/src/ir.c
+++ b/src/ir.c
@@ -404,6 +404,7 @@ typedef enum irAddrKind {
irAddr_Default,
// irAddr_Vector,
irAddr_Map,
+ irAddr_BitField,
} irAddrKind;
typedef struct irAddr {
@@ -415,6 +416,9 @@ typedef struct irAddr {
Type * map_type;
Type * map_result;
};
+ struct {
+ i32 bit_field_value_index;
+ };
};
// union {
// struct { irValue *index; } Vector;
@@ -434,6 +438,12 @@ irAddr ir_addr_map(irValue *addr, irValue *map_key, Type *map_type, Type *map_re
return v;
}
+irAddr ir_addr_bit_field(irValue *addr, isize bit_field_value_index) {
+ irAddr v = {irAddr_BitField, addr};
+ v.bit_field_value_index = bit_field_value_index;
+ return v;
+}
+
typedef enum irDebugEncoding {
irDebugBasicEncoding_Invalid = 0,
@@ -1078,9 +1088,12 @@ irValue *ir_emit(irProcedure *proc, irValue *instr) {
irValue *ir_const_int(gbAllocator a, i64 i) {
return ir_value_constant(a, t_int, exact_value_i64(i));
}
-irValue *ir_const_i32(gbAllocator a, i64 i) {
+irValue *ir_const_i32(gbAllocator a, i32 i) {
return ir_value_constant(a, t_i32, exact_value_i64(i));
}
+irValue *ir_const_u32(gbAllocator a, u32 i) {
+ return ir_value_constant(a, t_u32, exact_value_i64(i));
+}
irValue *ir_const_i64(gbAllocator a, i64 i) {
return ir_value_constant(a, t_i64, exact_value_i64(i));
}
@@ -1734,12 +1747,82 @@ irValue *ir_insert_dynamic_map_key_and_value(irProcedure *proc, irValue *addr, T
}
+irValue *ir_emit_ptr_offset(irProcedure *proc, irValue *ptr, irValue *offset);
+irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *right, Type *type);
+
irValue *ir_addr_store(irProcedure *proc, irAddr addr, irValue *value) {
if (addr.addr == NULL) {
return NULL;
}
if (addr.kind == irAddr_Map) {
return ir_insert_dynamic_map_key_and_value(proc, addr.addr, addr.map_type, addr.map_key, value);
+ } else if (addr.kind == irAddr_BitField) {
+ gbAllocator a = proc->module->allocator;
+
+ Type *bft = base_type(type_deref(ir_type(addr.addr)));
+ GB_ASSERT(is_type_bit_field(bft));
+ i32 value_index = addr.bit_field_value_index;
+ i32 offset = bft->BitField.offsets[value_index];
+ i32 size_in_bits = bft->BitField.fields[value_index]->type->BitFieldValue.bits;
+
+ i32 byte_index = offset / 8;
+ i32 bit_inset = offset % 8;
+
+ i32 size_in_bytes = next_pow2((size_in_bits+7)/8);
+ if (size_in_bytes == 0) {
+ GB_ASSERT(size_in_bits == 0);
+ return NULL;
+ }
+
+ Type *int_type = NULL;
+ switch (size_in_bytes) {
+ case 1: int_type = t_u8; break;
+ case 2: int_type = t_u16; break;
+ case 4: int_type = t_u32; break;
+ case 8: int_type = t_u64; break;
+ case 16: int_type = t_u128; break;
+ }
+ GB_ASSERT(int_type != NULL);
+
+ value = ir_emit_conv(proc, value, int_type);
+
+ irValue *bytes = ir_emit_conv(proc, addr.addr, t_u8_ptr);
+ bytes = ir_emit_ptr_offset(proc, bytes, ir_const_int(a, byte_index));
+
+
+ if (bit_inset == 0) {
+ irValue *v = value;
+ i32 sa = 8*size_in_bytes - size_in_bits;
+ if (sa > 0) {
+ irValue *shift_amount = ir_const_int(a, sa);
+ v = ir_emit_arith(proc, Token_Shl, v, shift_amount, int_type);
+ v = ir_emit_arith(proc, Token_Shr, v, shift_amount, int_type);
+ }
+ irValue *ptr = ir_emit_conv(proc, bytes, make_type_pointer(a, int_type));
+ v = ir_emit_arith(proc, Token_Or, ir_emit_load(proc, ptr), v, int_type);
+ return ir_emit_store(proc, ptr, v);
+ }
+
+
+ // First byte
+ {
+ i32 sa = 8 - bit_inset;
+ irValue *shift_amount = ir_const_int(a, sa);
+ irValue *v = ir_emit_conv(proc, value, t_u8);
+ v = ir_emit_arith(proc, Token_Shl, v, shift_amount, int_type);
+ v = ir_emit_arith(proc, Token_Or, ir_emit_load(proc, bytes), v, int_type);
+ ir_emit_store(proc, bytes, v);
+
+ }
+
+ // Remaining bytes
+ {
+ irValue *shift_amount = ir_const_int(a, bit_inset);
+ irValue *ptr = ir_emit_conv(proc, ir_emit_ptr_offset(proc, bytes, v_one), make_type_pointer(a, int_type));
+ irValue *v = ir_emit_arith(proc, Token_Shr, value, shift_amount, int_type);
+ v = ir_emit_arith(proc, Token_Or, ir_emit_load(proc, ptr), v, int_type);
+ return ir_emit_store(proc, ptr, v);
+ }
}
irValue *v = ir_emit_conv(proc, value, ir_addr_type(addr));
@@ -1787,12 +1870,62 @@ irValue *ir_addr_load(irProcedure *proc, irAddr addr) {
irValue *single = ir_emit_struct_ep(proc, v, 0);
return ir_emit_load(proc, single);
}
+ } else if (addr.kind == irAddr_BitField) {
+ gbAllocator a = proc->module->allocator;
+
+
+ Type *bft = base_type(type_deref(ir_type(addr.addr)));
+ GB_ASSERT(is_type_bit_field(bft));
+ i32 value_index = addr.bit_field_value_index;
+ i32 offset = bft->BitField.offsets[value_index];
+ i32 size_in_bits = bft->BitField.fields[value_index]->type->BitFieldValue.bits;
+
+ i32 byte_index = offset / 8;
+ i32 bit_inset = offset % 8;
+
+ i32 size_in_bytes = next_pow2((size_in_bits+7)/8);
+ if (size_in_bytes == 0) {
+ GB_ASSERT(size_in_bits == 0);
+ return ir_const_i32(a, 0);
+ }
+
+ Type *int_type = NULL;
+ switch (size_in_bytes) {
+ case 1: int_type = t_u8; break;
+ case 2: int_type = t_u16; break;
+ case 4: int_type = t_u32; break;
+ case 8: int_type = t_u64; break;
+ case 16: int_type = t_u128; break;
+ }
+ GB_ASSERT(int_type != NULL);
+
+
+ irValue *bytes = ir_emit_conv(proc, addr.addr, t_u8_ptr);
+ bytes = ir_emit_ptr_offset(proc, bytes, ir_const_int(a, byte_index));
+
+ Type *int_ptr = make_type_pointer(a, int_type);
+
+ if (bit_inset == 0) {
+ irValue *v = ir_emit_load(proc, ir_emit_conv(proc, bytes, int_ptr));
+ i32 sa = 8*size_in_bytes - size_in_bits;
+ if (sa > 0) {
+ irValue *shift_amount = ir_const_int(a, sa);
+ v = ir_emit_arith(proc, Token_Shl, v, shift_amount, int_type);
+ v = ir_emit_arith(proc, Token_Shr, v, shift_amount, int_type);
+ }
+ return v;
+ }
+
+
+ irValue *first_byte = ir_emit_load(proc, bytes);
+ irValue *res = ir_emit_arith(proc, Token_Shr, first_byte, ir_const_int(a, 8 - bit_inset), int_type);
+
+ irValue *remaining_bytes = ir_emit_load(proc, ir_emit_conv(proc, ir_emit_ptr_offset(proc, bytes, v_one), int_ptr));
+ remaining_bytes = ir_emit_arith(proc, Token_Shl, remaining_bytes, ir_const_int(a, bit_inset), int_type);
+ return ir_emit_arith(proc, Token_Or, res, remaining_bytes, int_type);
+
}
- // if (addr.kind == irAddr_Vector) {
- // irValue *v = ir_emit_load(proc, addr.addr);
- // return ir_emit(proc, ir_instr_extract_element(proc, v, addr.Vector.index));
- // }
Type *t = base_type(ir_type(addr.addr));
if (t->kind == Type_Proc) {
// NOTE(bill): Imported procedures don't require a load as they are pointers
@@ -2664,8 +2797,39 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
// float -> float
if (is_type_float(src) && is_type_float(dst)) {
+ gbAllocator a = proc->module->allocator;
i64 sz = type_size_of(proc->module->allocator, src);
i64 dz = type_size_of(proc->module->allocator, dst);
+ if (sz == 2) {
+ switch (dz) {
+ case 2: return value;
+ case 4: {
+ irValue **args = gb_alloc_array(a, irValue *, 1);
+ args[0] = value;
+ return ir_emit_global_call(proc, "__gnu_h2f_ieee", args, 1);
+ } break;
+ case 8: {
+ irValue **args = gb_alloc_array(a, irValue *, 1);
+ args[0] = value;
+ return ir_emit_global_call(proc, "__f16_to_f64", args, 1);
+ } break;
+ }
+ } else if (dz == 2) {
+ switch (sz) {
+ case 2: return value;
+ case 4: {
+ irValue **args = gb_alloc_array(a, irValue *, 1);
+ args[0] = value;
+ return ir_emit_global_call(proc, "__gnu_f2h_ieee", args, 1);
+ } break;
+ case 8: {
+ irValue **args = gb_alloc_array(a, irValue *, 1);
+ args[0] = value;
+ return ir_emit_global_call(proc, "__truncdfhf2", args, 1);
+ } break;
+ }
+ }
+
irConvKind kind = irConv_fptrunc;
if (dz >= sz) {
kind = irConv_fpext;
@@ -2878,6 +3042,7 @@ bool ir_is_type_aggregate(Type *t) {
case Basic_any:
return true;
+ // case Basic_complex32:
case Basic_complex64:
case Basic_complex128:
return true;
@@ -3139,7 +3304,7 @@ isize ir_type_info_index(CheckerInfo *info, Type *type) {
}
if (entry_index < 0) {
- compiler_error("Type_Info for `%s` could not be found", type_to_string(type));
+ compiler_error("TypeInfo for `%s` could not be found", type_to_string(type));
}
return entry_index;
}
@@ -4668,9 +4833,18 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
Selection sel = lookup_field(proc->module->allocator, type, selector, false);
GB_ASSERT(sel.entity != NULL);
- irValue *a = ir_build_addr(proc, se->expr).addr;
- a = ir_emit_deep_field_gep(proc, a, sel);
- return ir_addr(a);
+ if (sel.entity->type->kind == Type_BitFieldValue) {
+ irAddr addr = ir_build_addr(proc, se->expr);
+ Type *bft = type_deref(ir_addr_type(addr));
+ GB_ASSERT(is_type_bit_field(bft));
+ GB_ASSERT(sel.index.count == 1);
+ i32 index = sel.index.e[0];
+ return ir_addr_bit_field(addr.addr, index);
+ } else {
+ irValue *a = ir_build_addr(proc, se->expr).addr;
+ a = ir_emit_deep_field_gep(proc, a, sel);
+ return ir_addr(a);
+ }
} else {
Type *type = type_deref(type_of_expr(proc->module->info, se->expr));
Type *selector_type = base_type(type_of_expr(proc->module->info, se->selector));
@@ -7311,7 +7485,7 @@ void ir_gen_tree(irGen *s) {
switch (t->kind) {
case Type_Named: {
- ir_emit_comment(proc, str_lit("Type_Info_Named"));
+ ir_emit_comment(proc, str_lit("TypeInfoNamed"));
tag = ir_emit_conv(proc, ti_ptr, t_type_info_named_ptr);
// TODO(bill): Which is better? The mangled name or actual name?
@@ -7323,11 +7497,12 @@ void ir_gen_tree(irGen *s) {
} break;
case Type_Basic:
- ir_emit_comment(proc, str_lit("Type_Info_Basic"));
+ ir_emit_comment(proc, str_lit("TypeInfoBasic"));
switch (t->Basic.kind) {
case Basic_bool:
tag = ir_emit_conv(proc, ti_ptr, t_type_info_boolean_ptr);
break;
+
case Basic_i8:
case Basic_u8:
case Basic_i16:
@@ -7341,20 +7516,21 @@ void ir_gen_tree(irGen *s) {
case Basic_int:
case Basic_uint: {
tag = ir_emit_conv(proc, ti_ptr, t_type_info_integer_ptr);
- bool is_unsigned = (t->Basic.flags & BasicFlag_Unsigned) != 0;
- irValue *is_signed = ir_const_bool(a, !is_unsigned);
+ irValue *is_signed = ir_const_bool(a, (t->Basic.flags & BasicFlag_Unsigned) == 0);
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), is_signed);
} break;
+ // case Basic_f16:
case Basic_f32:
- case Basic_f64: {
+ case Basic_f64:
tag = ir_emit_conv(proc, ti_ptr, t_type_info_float_ptr);
- } break;
+ break;
+ // case Basic_complex32:
case Basic_complex64:
- case Basic_complex128: {
+ case Basic_complex128:
tag = ir_emit_conv(proc, ti_ptr, t_type_info_complex_ptr);
- } break;
+ break;
case Basic_rawptr:
tag = ir_emit_conv(proc, ti_ptr, t_type_info_pointer_ptr);
@@ -7371,19 +7547,19 @@ void ir_gen_tree(irGen *s) {
break;
case Type_Pointer: {
- ir_emit_comment(proc, str_lit("Type_Info_Pointer"));
+ ir_emit_comment(proc, str_lit("TypeInfoPointer"));
tag = ir_emit_conv(proc, ti_ptr, t_type_info_pointer_ptr);
irValue *gep = ir_get_type_info_ptr(proc, t->Pointer.elem);
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), gep);
} break;
case Type_Atomic: {
- ir_emit_comment(proc, str_lit("Type_Info_Atomic"));
+ ir_emit_comment(proc, str_lit("TypeInfoAtomic"));
tag = ir_emit_conv(proc, ti_ptr, t_type_info_atomic_ptr);
irValue *gep = ir_get_type_info_ptr(proc, t->Atomic.elem);
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), gep);
} break;
case Type_Array: {
- ir_emit_comment(proc, str_lit("Type_Info_Array"));
+ ir_emit_comment(proc, str_lit("TypeInfoArray"));
tag = ir_emit_conv(proc, ti_ptr, t_type_info_array_ptr);
irValue *gep = ir_get_type_info_ptr(proc, t->Array.elem);
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), gep);
@@ -7397,7 +7573,7 @@ void ir_gen_tree(irGen *s) {
} break;
case Type_DynamicArray: {
- ir_emit_comment(proc, str_lit("Type_Info_DynamicArray"));
+ ir_emit_comment(proc, str_lit("TypeInfoDynamicArray"));
tag = ir_emit_conv(proc, ti_ptr, t_type_info_dynamic_array_ptr);
irValue *gep = ir_get_type_info_ptr(proc, t->DynamicArray.elem);
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), gep);
@@ -7407,7 +7583,7 @@ void ir_gen_tree(irGen *s) {
ir_emit_store(proc, elem_size, ir_const_int(a, ez));
} break;
case Type_Slice: {
- ir_emit_comment(proc, str_lit("Type_Info_Slice"));
+ ir_emit_comment(proc, str_lit("TypeInfoSlice"));
tag = ir_emit_conv(proc, ti_ptr, t_type_info_slice_ptr);
irValue *gep = ir_get_type_info_ptr(proc, t->Slice.elem);
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), gep);
@@ -7417,7 +7593,7 @@ void ir_gen_tree(irGen *s) {
ir_emit_store(proc, elem_size, ir_const_int(a, ez));
} break;
case Type_Vector: {
- ir_emit_comment(proc, str_lit("Type_Info_Vector"));
+ ir_emit_comment(proc, str_lit("TypeInfoVector"));
tag = ir_emit_conv(proc, ti_ptr, t_type_info_vector_ptr);
irValue *gep = ir_get_type_info_ptr(proc, t->Vector.elem);
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), gep);
@@ -7428,7 +7604,7 @@ void ir_gen_tree(irGen *s) {
} break;
case Type_Proc: {
- ir_emit_comment(proc, str_lit("Type_Info_Proc"));
+ ir_emit_comment(proc, str_lit("TypeInfoProc"));
tag = ir_emit_conv(proc, ti_ptr, t_type_info_procedure_ptr);
irValue *params = ir_emit_struct_ep(proc, tag, 2);
@@ -7445,10 +7621,10 @@ void ir_gen_tree(irGen *s) {
ir_emit_store(proc, variadic, ir_const_bool(a, t->Proc.variadic));
ir_emit_store(proc, convention, ir_const_int(a, t->Proc.calling_convention));
- // TODO(bill): Type_Info for procedures
+ // TODO(bill): TypeInfo for procedures
} break;
case Type_Tuple: {
- ir_emit_comment(proc, str_lit("Type_Info_Tuple"));
+ ir_emit_comment(proc, str_lit("TypeInfoTuple"));
tag = ir_emit_conv(proc, ti_ptr, t_type_info_tuple_ptr);
irValue *record = ir_emit_struct_ep(proc, tag, 2);
@@ -7476,7 +7652,7 @@ void ir_gen_tree(irGen *s) {
case Type_Record: {
switch (t->Record.kind) {
case TypeRecord_Struct: {
- ir_emit_comment(proc, str_lit("Type_Info_Struct"));
+ ir_emit_comment(proc, str_lit("TypeInfoStruct"));
tag = ir_emit_conv(proc, ti_ptr, t_type_info_struct_ptr);
irValue *record = ir_emit_struct_ep(proc, tag, 2);
@@ -7523,7 +7699,7 @@ void ir_gen_tree(irGen *s) {
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 3), memory_usings, count, count);
} break;
case TypeRecord_Union: {
- ir_emit_comment(proc, str_lit("Type_Info_Union"));
+ ir_emit_comment(proc, str_lit("TypeInfoUnion"));
tag = ir_emit_conv(proc, ti_ptr, t_type_info_union_ptr);
{
@@ -7591,7 +7767,7 @@ void ir_gen_tree(irGen *s) {
} break;
case TypeRecord_RawUnion: {
- ir_emit_comment(proc, str_lit("Type_Info_RawUnion"));
+ ir_emit_comment(proc, str_lit("TypeInfoRawUnion"));
tag = ir_emit_conv(proc, ti_ptr, t_type_info_raw_union_ptr);
irValue *record = ir_emit_struct_ep(proc, tag, 2);
@@ -7618,7 +7794,7 @@ void ir_gen_tree(irGen *s) {
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 2), memory_offsets, count, count);
} break;
case TypeRecord_Enum:
- ir_emit_comment(proc, str_lit("Type_Info_Enum"));
+ ir_emit_comment(proc, str_lit("TypeInfoEnum"));
tag = ir_emit_conv(proc, ti_ptr, t_type_info_enum_ptr);
{
GB_ASSERT(t->Record.enum_base_type != NULL);
@@ -7659,22 +7835,18 @@ void ir_gen_tree(irGen *s) {
irValue *names = ir_emit_struct_ep(proc, tag, 3);
irValue *name_array_elem = ir_array_elem(proc, name_array);
-
- ir_emit_store(proc, ir_emit_struct_ep(proc, names, 0), name_array_elem);
- ir_emit_store(proc, ir_emit_struct_ep(proc, names, 1), v_count);
+ ir_fill_slice(proc, names, name_array_elem, v_count, v_count);
irValue *values = ir_emit_struct_ep(proc, tag, 4);
irValue *value_array_elem = ir_array_elem(proc, value_array);
-
- ir_emit_store(proc, ir_emit_struct_ep(proc, values, 0), value_array_elem);
- ir_emit_store(proc, ir_emit_struct_ep(proc, values, 1), v_count);
+ ir_fill_slice(proc, values, value_array_elem, v_count, v_count);
}
}
break;
}
} break;
case Type_Map: {
- ir_emit_comment(proc, str_lit("Type_Info_Map"));
+ ir_emit_comment(proc, str_lit("TypeInfoMap"));
tag = ir_emit_conv(proc, ti_ptr, t_type_info_map_ptr);
irValue *key = ir_emit_struct_ep(proc, tag, 2);
@@ -7687,6 +7859,49 @@ void ir_gen_tree(irGen *s) {
ir_emit_store(proc, generated_struct, ir_get_type_info_ptr(proc, t->Map.generated_struct_type));
ir_emit_store(proc, count, ir_const_int(a, t->Map.count));
} break;
+
+ case Type_BitField: {
+ ir_emit_comment(proc, str_lit("TypeInfoBitField"));
+ tag = ir_emit_conv(proc, ti_ptr, t_type_info_map_ptr);
+ // names: []string,
+ // bits: []u32,
+ // offsets: []u32,
+ isize count = t->BitField.field_count;
+ if (count > 0) {
+ Entity **fields = t->BitField.fields;
+ irValue *name_array = ir_generate_array(m, t_string, count, str_lit("__$bit_field_names"), cast(i64)entry_index);
+ irValue *bit_array = ir_generate_array(m, t_u32, count, str_lit("__$bit_field_bits"), cast(i64)entry_index);
+ irValue *offset_array = ir_generate_array(m, t_u32, count, str_lit("__$bit_field_offsets"), cast(i64)entry_index);
+
+ for (isize i = 0; i < count; i++) {
+ Entity *f = fields[i];
+ GB_ASSERT(f->type != NULL);
+ GB_ASSERT(f->type->kind == Type_BitFieldValue);
+ irValue *name_ep = ir_emit_array_epi(proc, name_array, i);
+ irValue *bit_ep = ir_emit_array_epi(proc, bit_array, i);
+ irValue *offset_ep = ir_emit_array_epi(proc, offset_array, i);
+
+ ir_emit_store(proc, name_ep, ir_const_string(a, f->token.string));
+ ir_emit_store(proc, bit_ep, ir_const_u32(a, f->type->BitFieldValue.bits));
+ ir_emit_store(proc, offset_ep, ir_const_u32(a, t->BitField.offsets[i]));
+
+ }
+
+ irValue *v_count = ir_const_int(a, count);
+
+ irValue *names = ir_emit_struct_ep(proc, tag, 3);
+ irValue *name_array_elem = ir_array_elem(proc, name_array);
+ ir_fill_slice(proc, names, name_array_elem, v_count, v_count);
+
+ irValue *bits = ir_emit_struct_ep(proc, tag, 4);
+ irValue *bit_array_elem = ir_array_elem(proc, bit_array);
+ ir_fill_slice(proc, bits, bit_array_elem, v_count, v_count);
+
+ irValue *offsets = ir_emit_struct_ep(proc, tag, 5);
+ irValue *offset_array_elem = ir_array_elem(proc, offset_array);
+ ir_fill_slice(proc, offsets, offset_array_elem, v_count, v_count);
+ }
+ } break;
}
@@ -7707,7 +7922,7 @@ void ir_gen_tree(irGen *s) {
}
GB_ASSERT_MSG(found, "%s", type_to_string(tag_type));
} else {
- GB_PANIC("Unhandled Type_Info type: %s", type_to_string(t));
+ GB_PANIC("Unhandled TypeInfo type: %s", type_to_string(t));
}
}
}
diff --git a/src/ir_print.c b/src/ir_print.c
index 520390d55..d66a99c23 100644
--- a/src/ir_print.c
+++ b/src/ir_print.c
@@ -193,9 +193,11 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
case Basic_i128: ir_fprintf(f, "i128"); return;
case Basic_u128: ir_fprintf(f, "i128"); return;
+ // case Basic_f16: ir_fprintf(f, "half"); return;
case Basic_f32: ir_fprintf(f, "float"); return;
case Basic_f64: ir_fprintf(f, "double"); return;
+ // case Basic_complex32: ir_fprintf(f, "%%..complex32"); return;
case Basic_complex64: ir_fprintf(f, "%%..complex64"); return;
case Basic_complex128: ir_fprintf(f, "%%..complex128"); return;
@@ -348,6 +350,12 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
GB_ASSERT(t->Map.generated_struct_type != NULL);
ir_print_type(f, m, t->Map.generated_struct_type);
} break;
+
+ case Type_BitField: {
+ i64 align = type_align_of(heap_allocator(), t);
+ i64 size = type_size_of(heap_allocator(), t);
+ ir_fprintf(f, "{[0 x <%lld x i8>], [%lld x i8]}", align, size);
+ } break;
}
}
@@ -426,12 +434,17 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
// IMPORTANT NOTE(bill): LLVM requires all floating point constants to be
// a 64 bit number if bits_of(float type) <= 64.
// https://groups.google.com/forum/#!topic/llvm-dev/IlqV3TbSk6M
- // 64 bit mantiir: 52 bits
- // 32 bit mantiir: 23 bits
+ // 64 bit mantissa: 52 bits
+ // 32 bit mantissa: 23 bits
+ // 16 bit mantissa: 10 bits
// 29 == 52-23
u >>= 29;
u <<= 29;
break;
+ // case Basic_f16:
+ // u >>= 42;
+ // u <<= 42;
+ // break;
}
switch (type->Basic.kind) {
@@ -1568,6 +1581,8 @@ void print_llvm_ir(irGen *ir) {
ir_print_encoded_local(f, str_lit("..rawptr"));
ir_fprintf(f, " = type i8* ; Basic_rawptr\n");
+ ir_print_encoded_local(f, str_lit("..complex32"));
+ ir_fprintf(f, " = type {half, half} ; Basic_complex32\n");
ir_print_encoded_local(f, str_lit("..complex64"));
ir_fprintf(f, " = type {float, float} ; Basic_complex64\n");
ir_print_encoded_local(f, str_lit("..complex128"));
diff --git a/src/parser.c b/src/parser.c
index 076f72a14..4c7cc50af 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -397,6 +397,11 @@ AST_NODE_KIND(_TypeBegin, "", i32) \
AstNode *base_type; \
AstNodeArray fields; /* FieldValue */ \
}) \
+ AST_NODE_KIND(BitFieldType, "bit field type", struct { \
+ Token token; \
+ AstNodeArray fields; /* FieldValue with : */ \
+ AstNode *align; \
+ }) \
AST_NODE_KIND(MapType, "map type", struct { \
Token token; \
AstNode *count; \
@@ -547,6 +552,7 @@ Token ast_node_token(AstNode *node) {
case AstNode_UnionType: return node->UnionType.token;
case AstNode_RawUnionType: return node->RawUnionType.token;
case AstNode_EnumType: return node->EnumType.token;
+ case AstNode_BitFieldType: return node->BitFieldType.token;
case AstNode_MapType: return node->MapType.token;
}
@@ -804,6 +810,9 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
n->EnumType.base_type = clone_ast_node(a, n->EnumType.base_type);
n->EnumType.fields = clone_ast_node_array(a, n->EnumType.fields);
break;
+ case AstNode_BitFieldType:
+ n->BitFieldType.fields = clone_ast_node_array(a, n->BitFieldType.fields);
+ n->BitFieldType.align = clone_ast_node(a, n->BitFieldType.align);
case AstNode_MapType:
n->MapType.count = clone_ast_node(a, n->MapType.count);
n->MapType.key = clone_ast_node(a, n->MapType.key);
@@ -1384,6 +1393,14 @@ AstNode *ast_enum_type(AstFile *f, Token token, AstNode *base_type, AstNodeArray
return result;
}
+AstNode *ast_bit_field_type(AstFile *f, Token token, AstNodeArray fields, AstNode *align) {
+ AstNode *result = make_ast_node(f, AstNode_BitFieldType);
+ result->BitFieldType.token = token;
+ result->BitFieldType.fields = fields;
+ result->BitFieldType.align = align;
+ return result;
+}
+
AstNode *ast_map_type(AstFile *f, Token token, AstNode *count, AstNode *key, AstNode *value) {
AstNode *result = make_ast_node(f, AstNode_MapType);
result->MapType.token = token;
@@ -1622,6 +1639,7 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
case AstNode_UnionType:
case AstNode_RawUnionType:
case AstNode_EnumType:
+ case AstNode_BitFieldType:
return true;
case AstNode_ProcLit:
return s->ProcLit.body != NULL;
@@ -3128,6 +3146,51 @@ AstNode *parse_type_or_ident(AstFile *f) {
return ast_enum_type(f, token, base_type, values);
}
+ case Token_bit_field: {
+ Token token = expect_token(f, Token_bit_field);
+ AstNodeArray fields = make_ast_node_array(f);
+ AstNode *align = NULL;
+ Token open, close;
+
+ isize prev_level = f->expr_level;
+ f->expr_level = -1;
+
+ while (allow_token(f, Token_Hash)) {
+ Token tag = expect_token_after(f, Token_Ident, "#");
+ if (str_eq(tag.string, str_lit("align"))) {
+ if (align) {
+ syntax_error(tag, "Duplicate bit_field tag `#%.*s`", LIT(tag.string));
+ }
+ align = parse_expr(f, true);
+ } else {
+ syntax_error(tag, "Invalid bit_field tag `#%.*s`", LIT(tag.string));
+ }
+ }
+
+ f->expr_level = prev_level;
+
+ open = expect_token_after(f, Token_OpenBrace, "bit_field");
+
+ while (f->curr_token.kind != Token_EOF &&
+ f->curr_token.kind != Token_CloseBrace) {
+ AstNode *name = parse_ident(f);
+ Token colon = expect_token(f, Token_Colon);
+ AstNode *value = parse_expr(f, true);
+
+ AstNode *field = ast_field_value(f, name, value, colon);
+ array_add(&fields, field);
+
+ if (f->curr_token.kind != Token_Comma) {
+ break;
+ }
+ next_token(f);
+ }
+
+ close = expect_token(f, Token_CloseBrace);
+
+ return ast_bit_field_type(f, token, fields, align);
+ }
+
case Token_proc: {
Token token = f->curr_token;
AstNode *pt = parse_proc_type(f, NULL, NULL, NULL);
diff --git a/src/ssa.c b/src/ssa.c
index db3de5e72..b8e3f0b8d 100644
--- a/src/ssa.c
+++ b/src/ssa.c
@@ -2289,7 +2289,7 @@ void ssa_print_exact_value(gbFile *f, ssaValue *v) {
u64 x = *cast(u64 *)&fp;
gb_fprintf(f, " [0x%llx]", cast(unsigned long long)x);
} else {
- GB_PANIC("unhandled integer");
+ GB_PANIC("unhandled float");
}
break;
case ExactValue_String:
diff --git a/src/tokenizer.c b/src/tokenizer.c
index 8d30a36a1..868ed93cc 100644
--- a/src/tokenizer.c
+++ b/src/tokenizer.c
@@ -100,6 +100,7 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
TOKEN_KIND(Token_union, "union"), \
TOKEN_KIND(Token_raw_union, "raw_union"), \
TOKEN_KIND(Token_enum, "enum"), \
+ TOKEN_KIND(Token_bit_field, "bit_field"), \
TOKEN_KIND(Token_vector, "vector"), \
TOKEN_KIND(Token_static, "static"), \
TOKEN_KIND(Token_dynamic, "dynamic"), \
@@ -889,6 +890,10 @@ Token tokenizer_get_token(Tokenizer *t) {
case '}': token.kind = Token_CloseBrace; break;
case '\\': token.kind = Token_BackSlash; break;
+ case '≠': token.kind = Token_NotEq; break;
+ case '≤': token.kind = Token_LtEq; break;
+ case '≥': token.kind = Token_GtEq; break;
+
case '%': token.kind = token_kind_dub_eq(t, '%', Token_Mod, Token_ModEq, Token_ModMod, Token_ModModEq); break;
case '*': token.kind = token_kind_variant2(t, Token_Mul, Token_MulEq); break;
diff --git a/src/types.c b/src/types.c
index cbb0bd0d9..91d8dc4eb 100644
--- a/src/types.c
+++ b/src/types.c
@@ -14,9 +14,11 @@ typedef enum BasicKind {
Basic_i128,
Basic_u128,
+ // Basic_f16,
Basic_f32,
Basic_f64,
+ // Basic_complex32,
Basic_complex64,
Basic_complex128,
@@ -149,6 +151,15 @@ typedef struct TypeRecord {
Type *generated_struct_type; \
Type *lookup_result_type; \
}) \
+ TYPE_KIND(BitFieldValue, struct { u32 bits; }) \
+ TYPE_KIND(BitField, struct { \
+ Scope * scope; \
+ Entity **fields; \
+ i32 field_count; \
+ u32 * offsets; \
+ u32 * sizes; \
+ i64 custom_align; \
+ }) \
@@ -225,9 +236,11 @@ gb_global Type basic_types[] = {
{Type_Basic, {Basic_u128, BasicFlag_Integer | BasicFlag_Unsigned, 16, STR_LIT("u128")}},
+ // {Type_Basic, {Basic_f16, BasicFlag_Float, 2, STR_LIT("f16")}},
{Type_Basic, {Basic_f32, BasicFlag_Float, 4, STR_LIT("f32")}},
{Type_Basic, {Basic_f64, BasicFlag_Float, 8, STR_LIT("f64")}},
+ // {Type_Basic, {Basic_complex32, BasicFlag_Complex, 4, STR_LIT("complex32")}},
{Type_Basic, {Basic_complex64, BasicFlag_Complex, 8, STR_LIT("complex64")}},
{Type_Basic, {Basic_complex128, BasicFlag_Complex, 16, STR_LIT("complex128")}},
@@ -265,9 +278,11 @@ gb_global Type *t_u64 = &basic_types[Basic_u64];
gb_global Type *t_i128 = &basic_types[Basic_i128];
gb_global Type *t_u128 = &basic_types[Basic_u128];
+// 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_complex32 = &basic_types[Basic_complex32];
gb_global Type *t_complex64 = &basic_types[Basic_complex64];
gb_global Type *t_complex128 = &basic_types[Basic_complex128];
@@ -325,6 +340,7 @@ gb_global Type *t_type_info_raw_union = NULL;
gb_global Type *t_type_info_union = NULL;
gb_global Type *t_type_info_enum = NULL;
gb_global Type *t_type_info_map = NULL;
+gb_global Type *t_type_info_bit_field = NULL;
gb_global Type *t_type_info_named_ptr = NULL;
gb_global Type *t_type_info_integer_ptr = NULL;
@@ -347,6 +363,7 @@ gb_global Type *t_type_info_raw_union_ptr = NULL;
gb_global Type *t_type_info_union_ptr = NULL;
gb_global Type *t_type_info_enum_ptr = NULL;
gb_global Type *t_type_info_map_ptr = NULL;
+gb_global Type *t_type_info_bit_field_ptr = NULL;
gb_global Type *t_allocator = NULL;
gb_global Type *t_allocator_ptr = NULL;
@@ -560,8 +577,21 @@ Type *make_type_map(gbAllocator a, i64 count, Type *key, Type *value) {
return t;
}
+Type *make_type_bit_field_value(gbAllocator a, u32 bits) {
+ Type *t = alloc_type(a, Type_BitFieldValue);
+ t->BitFieldValue.bits = bits;
+ return t;
+}
+
+Type *make_type_bit_field(gbAllocator a) {
+ Type *t = alloc_type(a, Type_BitField);
+ return t;
+}
+
+////////////////////////////////////////////////////////////////
+
Type *type_deref(Type *t) {
if (t != NULL) {
@@ -777,6 +807,7 @@ Type *base_complex_elem_type(Type *t) {
t = core_type(t);
if (is_type_complex(t)) {
switch (t->Basic.kind) {
+ // case Basic_complex32: return t_f16;
case Basic_complex64: return t_f32;
case Basic_complex128: return t_f64;
case Basic_UntypedComplex: return t_untyped_float;
@@ -802,7 +833,14 @@ bool is_type_enum(Type *t) {
t = base_type(t);
return (t->kind == Type_Record && t->Record.kind == TypeRecord_Enum);
}
-
+bool is_type_bit_field(Type *t) {
+ t = base_type(t);
+ return (t->kind == Type_BitField);
+}
+bool is_type_bit_field_value(Type *t) {
+ t = base_type(t);
+ return (t->kind == Type_BitFieldValue);
+}
bool is_type_map(Type *t) {
t = base_type(t);
return t->kind == Type_Map;
@@ -1067,6 +1105,26 @@ Type *default_type(Type *type) {
return type;
}
+Type *default_bit_field_value_type(Type *type) {
+ if (type == NULL) {
+ return t_invalid;
+ }
+ Type *t = base_type(type);
+ if (t->kind == Type_BitFieldValue) {
+ i32 bits = t->BitFieldValue.bits;
+ i32 size = 8*next_pow2((bits+7)/8);
+ switch (size) {
+ case 8: return t_u8;
+ case 16: return t_u16;
+ case 32: return t_u32;
+ case 64: return t_u64;
+ case 128: return t_u128;
+ default: GB_PANIC("Too big of a bit size!"); break;
+ }
+ }
+ return type;
+}
+
// NOTE(bill): Valid Compile time execution #run type
bool is_type_cte_safe(Type *type) {
type = default_type(base_type(type));
@@ -1211,8 +1269,9 @@ Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) {
i64 max_count = 0;
switch (type->kind) {
- case Type_Record: max_count = type->Record.field_count; break;
- case Type_Tuple: max_count = type->Tuple.variable_count; break;
+ case Type_Record: max_count = type->Record.field_count; break;
+ case Type_Tuple: max_count = type->Tuple.variable_count; break;
+ case Type_BitField: max_count = type->BitField.field_count; break;
}
if (index >= max_count) {
@@ -1244,6 +1303,14 @@ Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) {
}
}
break;
+
+ case Type_BitField: {
+ Array_i32 sel_array = {0};
+ array_init_count(&sel_array, a, 1);
+ sel_array.e[0] = cast(i32)index;
+ return make_selection(type->BitField.fields[index], sel_array, false);
+ } break;
+
}
GB_PANIC("Illegal index");
@@ -1407,6 +1474,21 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
return sel;
}
}
+ } else if (type->kind == Type_BitField) {
+ for (isize i = 0; i < type->BitField.field_count; i++) {
+ Entity *f = type->BitField.fields[i];
+ if (f->kind != Entity_Variable ||
+ (f->flags & EntityFlag_BitFieldValue) == 0) {
+ continue;
+ }
+
+ String str = f->token.string;
+ if (str_eq(field_name, str)) {
+ selection_add_index(&sel, i); // HACK(bill): Leaky memory
+ sel.entity = f;
+ return sel;
+ }
+ }
}
return sel;
@@ -1641,7 +1723,7 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
return max;
} break;
case TypeRecord_RawUnion: {
- i64 max = build_context.word_size;
+ i64 max = 1;
for (isize i = 0; i < t->Record.field_count; i++) {
Type *field_type = t->Record.fields[i]->type;
type_path_push(path, field_type);
@@ -1658,6 +1740,14 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
} break;
}
} break;
+
+ case Type_BitField: {
+ i64 align = 1;
+ if (t->BitField.custom_align > 0) {
+ align = t->BitField.custom_align;
+ }
+ return gb_clamp(next_pow2(align), 1, build_context.max_align);
+ } break;
}
// return gb_clamp(next_pow2(type_size_of(allocator, t)), 1, build_context.max_align);
@@ -1913,6 +2003,18 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
} break;
}
} break;
+
+ case Type_BitField: {
+ i64 align = 8*type_align_of_internal(allocator, t, path);
+ i64 end = 0;
+ if (t->BitField.field_count > 0) {
+ i64 last = t->BitField.field_count-1;
+ end = t->BitField.offsets[last] + t->BitField.sizes[last];
+ }
+ i64 bits = align_formula(end, align);
+ GB_ASSERT((bits%8) == 0);
+ return bits/8;
+ } break;
}
// Catch all
@@ -2009,8 +2111,6 @@ i64 type_offset_of_from_selection(gbAllocator allocator, Type *type, Selection s
return offset;
}
-
-
gbString write_type_to_string(gbString str, Type *type) {
if (type == NULL) {
return gb_string_appendc(str, "<no type>");
@@ -2191,8 +2291,9 @@ gbString write_type_to_string(gbString str, Type *type) {
case Type_Proc:
str = gb_string_appendc(str, "proc(");
- if (type->Proc.params)
+ if (type->Proc.params) {
str = write_type_to_string(str, type->Proc.params);
+ }
str = gb_string_appendc(str, ")");
if (type->Proc.results) {
str = gb_string_appendc(str, " -> ");
@@ -2213,6 +2314,32 @@ gbString write_type_to_string(gbString str, Type *type) {
break;
}
break;
+
+ case Type_BitField:
+ str = gb_string_appendc(str, "bit_field ");
+ if (type->BitField.custom_align != 0) {
+ str = gb_string_appendc(str, gb_bprintf("#align %d ", cast(int)type->BitField.custom_align));
+ }
+ str = gb_string_appendc(str, "{");
+
+ for (isize i = 0; i < type->BitField.field_count; i++) {
+ Entity *f = type->BitField.fields[i];
+ GB_ASSERT(f->kind == Entity_Variable);
+ GB_ASSERT(f->type != NULL && f->type->kind == Type_BitFieldValue);
+ str = gb_string_appendc(str, "{");
+ if (i > 0) {
+ str = gb_string_appendc(str, ", ");
+ }
+ str = gb_string_append_length(str, f->token.string.text, f->token.string.len);
+ str = gb_string_appendc(str, " : ");
+ str = gb_string_appendc(str, gb_bprintf("%lld", cast(long long)f->type->BitFieldValue.bits));
+ }
+ str = gb_string_appendc(str, "}");
+ break;
+
+ case Type_BitFieldValue:
+ str = gb_string_appendc(str, gb_bprintf("(bit field value with %lld bits)", cast(int)type->BitFieldValue.bits));
+ break;
}
return str;