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/ir.c | |
| 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/ir.c')
| -rw-r--r-- | src/ir.c | 291 |
1 files changed, 253 insertions, 38 deletions
@@ -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)); } } } |