diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-06-03 22:27:23 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-06-03 22:27:23 +0100 |
| commit | 2c0e59ae064b273899a56cb8d3c53b6967466fa2 (patch) | |
| tree | 0e1a9dc2ac94b7dfc408166f1cc1e0b921a5aba3 /src | |
| parent | 9d1a4c304a27c0b762809bc3c1d6c70fdb5137be (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.c | 4 | ||||
| -rw-r--r-- | src/check_expr.c | 140 | ||||
| -rw-r--r-- | src/check_stmt.c | 37 | ||||
| -rw-r--r-- | src/checker.c | 33 | ||||
| -rw-r--r-- | src/entity.c | 23 | ||||
| -rw-r--r-- | src/ir.c | 291 | ||||
| -rw-r--r-- | src/ir_print.c | 19 | ||||
| -rw-r--r-- | src/parser.c | 63 | ||||
| -rw-r--r-- | src/ssa.c | 2 | ||||
| -rw-r--r-- | src/tokenizer.c | 5 | ||||
| -rw-r--r-- | src/types.c | 141 |
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 @@ -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); @@ -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; |