authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-15 18:55:29-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-15 18:55:29-05:00
log1fc2082b4ccc2b75fba892bc9e27e9a5a3d821bf
tree1c63bda773e97c41bcbdfd68d3d880ef46c0bd8d
parent63d37b7cff0907cdf2361f1d61f19410fd6cc626

ability to declare const bitfields

See #261

6 files changed, 370 insertions(+), 86 deletions(-)

src/all_types.hpp+13-2
......@@ -873,11 +873,13 @@ struct TypeStructField {
873873 TypeTableEntry *type_entry;
874874 size_t src_index;
875875 size_t gen_index;
876 // offset from the memory at gen_index
877 size_t packed_bits_offset;
878 size_t packed_bits_size;
876879};
877880struct TypeTableEntryStruct {
878881 AstNode *decl_node;
879882 ContainerLayout layout;
880 bool is_packed;
881883 uint32_t src_field_count;
882884 uint32_t gen_field_count;
883885 TypeStructField *fields;
......@@ -1037,7 +1039,7 @@ struct TypeTableEntry {
10371039
10381040 // use these fields to make sure we don't duplicate type table entries for the same type
10391041 TypeTableEntry *pointer_parent[2][2]; // [0 - mut, 1 - const][0 - normal, 1 - volatile]
1040 TypeTableEntry *unknown_size_array_parent[2];
1042 TypeTableEntry *slice_parent[2]; // [0 - mut, 1 - const]
10411043 HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size;
10421044 TypeTableEntry *maybe_parent;
10431045 TypeTableEntry *error_parent;
......@@ -1193,6 +1195,14 @@ enum PanicMsgId {
11931195uint32_t fn_eval_hash(Scope*);
11941196bool fn_eval_eql(Scope *a, Scope *b);
11951197
1198struct IntTypeId {
1199 bool is_signed;
1200 uint8_t bit_count;
1201};
1202
1203uint32_t int_type_id_hash(IntTypeId);
1204bool int_type_id_eql(IntTypeId a, IntTypeId b);
1205
11961206struct CodeGen {
11971207 LLVMModuleRef module;
11981208 ZigList<ErrorMsg*> errors;
......@@ -1208,6 +1218,7 @@ struct CodeGen {
12081218 HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;
12091219 HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;
12101220 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table;
1221 HashMap<IntTypeId, TypeTableEntry *, int_type_id_hash, int_type_id_eql> int_type_table;
12111222 HashMap<FnTypeId *, TypeTableEntry *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
12121223 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
12131224 HashMap<GenericFnTypeId *, FnTableEntry *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;
src/analyze.cpp+202-19
......@@ -261,6 +261,24 @@ uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry) {
261261 }
262262}
263263
264// This has to do with packed structs
265static uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry) {
266 TypeTableEntry *canon_type = get_underlying_type(type_entry);
267
268 if (!type_has_bits(type_entry))
269 return 0;
270
271 if (canon_type->id == TypeTableEntryIdStruct && canon_type->data.structure.layout == ContainerLayoutPacked) {
272 uint64_t result = 0;
273 for (size_t i = 0; i < canon_type->data.structure.src_field_count; i += 1) {
274 result += type_size_bits(g, canon_type->data.structure.fields[i].type_entry);
275 }
276 return result;
277 }
278
279 return LLVMSizeOfTypeInBits(g->target_data_ref, canon_type->type_ref);
280}
281
264282static bool is_slice(TypeTableEntry *type) {
265283 return type->id == TypeTableEntryIdStruct && type->data.structure.is_slice;
266284}
......@@ -507,7 +525,7 @@ static void slice_type_common_init(CodeGen *g, TypeTableEntry *child_type,
507525 TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const);
508526
509527 unsigned element_count = 2;
510 entry->data.structure.is_packed = false;
528 entry->data.structure.layout = ContainerLayoutAuto;
511529 entry->data.structure.is_slice = true;
512530 entry->data.structure.src_field_count = element_count;
513531 entry->data.structure.gen_field_count = element_count;
......@@ -531,7 +549,7 @@ static void slice_type_common_init(CodeGen *g, TypeTableEntry *child_type,
531549
532550TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {
533551 assert(child_type->id != TypeTableEntryIdInvalid);
534 TypeTableEntry **parent_pointer = &child_type->unknown_size_array_parent[(is_const ? 1 : 0)];
552 TypeTableEntry **parent_pointer = &child_type->slice_parent[(is_const ? 1 : 0)];
535553
536554 if (*parent_pointer) {
537555 return *parent_pointer;
......@@ -1269,6 +1287,48 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
12691287 }
12701288}
12711289
1290static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
1291 TypeTableEntry *canon_type = get_underlying_type(type_entry);
1292 switch (canon_type->id) {
1293 case TypeTableEntryIdInvalid:
1294 case TypeTableEntryIdVar:
1295 zig_unreachable();
1296 case TypeTableEntryIdMetaType:
1297 case TypeTableEntryIdUnreachable:
1298 case TypeTableEntryIdNumLitFloat:
1299 case TypeTableEntryIdNumLitInt:
1300 case TypeTableEntryIdUndefLit:
1301 case TypeTableEntryIdNullLit:
1302 case TypeTableEntryIdErrorUnion:
1303 case TypeTableEntryIdPureError:
1304 case TypeTableEntryIdEnum:
1305 case TypeTableEntryIdEnumTag:
1306 case TypeTableEntryIdTypeDecl:
1307 case TypeTableEntryIdNamespace:
1308 case TypeTableEntryIdBlock:
1309 case TypeTableEntryIdBoundFn:
1310 case TypeTableEntryIdArgTuple:
1311 return false;
1312 case TypeTableEntryIdVoid:
1313 case TypeTableEntryIdBool:
1314 case TypeTableEntryIdInt:
1315 case TypeTableEntryIdFloat:
1316 case TypeTableEntryIdPointer:
1317 case TypeTableEntryIdArray:
1318 case TypeTableEntryIdUnion:
1319 case TypeTableEntryIdFn:
1320 return true;
1321 case TypeTableEntryIdStruct:
1322 return canon_type->data.structure.layout == ContainerLayoutPacked;
1323 case TypeTableEntryIdMaybe:
1324 {
1325 TypeTableEntry *canon_child_type = get_underlying_type(canon_type->data.maybe.child_type);
1326 return canon_child_type->id == TypeTableEntryIdPointer || canon_child_type->id == TypeTableEntryIdFn;
1327 }
1328 }
1329 zig_unreachable();
1330}
1331
12721332static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
12731333 // if you change the logic of this function likely you must make a similar change in
12741334 // parseh.cpp
......@@ -1307,22 +1367,77 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
13071367
13081368 Scope *scope = &struct_type->data.structure.decls_scope->base;
13091369
1370 size_t gen_field_index = 0;
1371 bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked);
1372 size_t packed_bits_offset = 0;
1373 size_t first_packed_bits_offset_misalign = SIZE_MAX;
1374 size_t debug_field_count = 0;
1375
13101376 for (size_t i = 0; i < field_count; i += 1) {
13111377 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
13121378 TypeTableEntry *field_type = type_struct_field->type_entry;
13131379
13141380 ensure_complete_type(g, field_type);
1381
13151382 if (type_is_invalid(field_type)) {
13161383 struct_type->data.structure.is_invalid = true;
1317 continue;
1384 break;
13181385 }
13191386
13201387 if (!type_has_bits(field_type))
13211388 continue;
13221389
1323 element_types[type_struct_field->gen_index] = field_type->type_ref;
1324 assert(element_types[type_struct_field->gen_index]);
1390 type_struct_field->gen_index = gen_field_index;
1391
1392 if (packed) {
1393 if (!type_allowed_in_packed_struct(field_type)) {
1394 AstNode *field_source_node = decl_node->data.container_decl.fields.at(i);
1395 add_node_error(g, field_source_node,
1396 buf_sprintf("packed structs cannot contain fields of type '%s'",
1397 buf_ptr(&field_type->name)));
1398 struct_type->data.structure.is_invalid = true;
1399 break;
1400 }
1401
1402 type_struct_field->packed_bits_size = type_size_bits(g, field_type);
1403
1404 size_t next_packed_bits_offset = packed_bits_offset + type_struct_field->packed_bits_size;
1405
1406 if (first_packed_bits_offset_misalign != SIZE_MAX) {
1407 // this field is not byte-aligned; it is part of the previous field with a bit offset
1408 type_struct_field->packed_bits_offset = packed_bits_offset - first_packed_bits_offset_misalign;
1409
1410 if (next_packed_bits_offset % 8 == 0) {
1411 // next field recovers byte alignment
1412 size_t full_bit_count = next_packed_bits_offset - first_packed_bits_offset_misalign;
1413 element_types[gen_field_index] = LLVMIntType(full_bit_count);
1414 gen_field_index += 1;
1415
1416 first_packed_bits_offset_misalign = SIZE_MAX;
1417 }
1418 } else if (next_packed_bits_offset % 8 != 0) {
1419 first_packed_bits_offset_misalign = packed_bits_offset;
1420 type_struct_field->packed_bits_offset = 0;
1421 } else {
1422 element_types[gen_field_index] = field_type->type_ref;
1423 type_struct_field->packed_bits_offset = 0;
1424 gen_field_index += 1;
1425 }
1426 packed_bits_offset = next_packed_bits_offset;
1427 } else {
1428 element_types[gen_field_index] = field_type->type_ref;
1429 assert(element_types[gen_field_index]);
1430
1431 gen_field_index += 1;
1432 }
1433 debug_field_count += 1;
13251434 }
1435 if (first_packed_bits_offset_misalign != SIZE_MAX) {
1436 size_t full_bit_count = packed_bits_offset - first_packed_bits_offset_misalign;
1437 element_types[gen_field_index] = LLVMIntType(full_bit_count);
1438 gen_field_index += 1;
1439 }
1440
13261441 struct_type->data.structure.embedded_in_current = false;
13271442 struct_type->data.structure.complete = true;
13281443
......@@ -1337,13 +1452,18 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
13371452 }
13381453 assert(struct_type->di_type);
13391454
1340 bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked);
1455
1456 // the count may have been adjusting from packing bit fields
1457 gen_field_count = gen_field_index;
1458 struct_type->data.structure.gen_field_count = gen_field_count;
1459
13411460 LLVMStructSetBody(struct_type->type_ref, element_types, gen_field_count, packed);
13421461 assert(LLVMStoreSizeOfType(g->target_data_ref, struct_type->type_ref) > 0);
13431462
1344 ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(gen_field_count);
1463 ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(debug_field_count);
13451464
13461465 ImportTableEntry *import = get_scope_import(scope);
1466 size_t debug_field_index = 0;
13471467 for (size_t i = 0; i < field_count; i += 1) {
13481468 AstNode *field_node = decl_node->data.container_decl.fields.at(i);
13491469 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
......@@ -1369,19 +1489,28 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
13691489 assert(field_type->type_ref);
13701490 assert(struct_type->type_ref);
13711491 assert(struct_type->data.structure.complete);
1372 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref);
1373 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, field_type->type_ref);
1374 uint64_t debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref,
1375 gen_field_index);
1376 di_element_types[gen_field_index] = ZigLLVMCreateDebugMemberType(g->dbuilder,
1492 uint64_t debug_size_in_bits;
1493 uint64_t debug_align_in_bits;
1494 uint64_t debug_offset_in_bits;
1495 if (packed) {
1496 debug_size_in_bits = type_struct_field->packed_bits_size;
1497 debug_align_in_bits = 1;
1498 debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref,
1499 gen_field_index) + type_struct_field->packed_bits_offset;
1500 } else {
1501 debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref);
1502 debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, field_type->type_ref);
1503 debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref, gen_field_index);
1504 }
1505 di_element_types[debug_field_index] = ZigLLVMCreateDebugMemberType(g->dbuilder,
13771506 ZigLLVMTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name),
13781507 import->di_file, field_node->line + 1,
13791508 debug_size_in_bits,
13801509 debug_align_in_bits,
13811510 debug_offset_in_bits,
13821511 0, field_di_type);
1383
1384 assert(di_element_types[gen_field_index]);
1512 assert(di_element_types[debug_field_index]);
1513 debug_field_index += 1;
13851514 }
13861515
13871516
......@@ -1393,7 +1522,7 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
13931522 import->di_file, decl_node->line + 1,
13941523 debug_size_in_bits,
13951524 debug_align_in_bits,
1396 0, nullptr, di_element_types, gen_field_count, 0, nullptr, "");
1525 0, nullptr, di_element_types, debug_field_count, 0, nullptr, "");
13971526
13981527 ZigLLVMReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type);
13991528 struct_type->di_type = replacement_di_type;
......@@ -2672,7 +2801,7 @@ bool is_node_void_expr(AstNode *node) {
26722801 return false;
26732802}
26742803
2675TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, size_t size_in_bits) {
2804TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, uint8_t size_in_bits) {
26762805 size_t index;
26772806 if (size_in_bits == 8) {
26782807 index = 0;
......@@ -2683,13 +2812,25 @@ TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, size_t size_in_bit
26832812 } else if (size_in_bits == 64) {
26842813 index = 3;
26852814 } else {
2686 zig_unreachable();
2815 return nullptr;
26872816 }
26882817 return &g->builtin_types.entry_int[is_signed ? 0 : 1][index];
26892818}
26902819
2691TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, size_t size_in_bits) {
2692 return *get_int_type_ptr(g, is_signed, size_in_bits);
2820TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, uint8_t size_in_bits) {
2821 TypeTableEntry **common_entry = get_int_type_ptr(g, is_signed, size_in_bits);
2822 if (common_entry)
2823 return *common_entry;
2824
2825 {
2826 auto entry = g->int_type_table.maybe_get({is_signed, size_in_bits});
2827 if (entry)
2828 return entry->value;
2829 }
2830
2831 TypeTableEntry *new_entry = make_int_type(g, is_signed, size_in_bits);
2832 g->int_type_table.put({is_signed, size_in_bits}, new_entry);
2833 return new_entry;
26932834}
26942835
26952836TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) {
......@@ -3703,3 +3844,45 @@ void render_const_value(Buf *buf, ConstExprValue *const_val) {
37033844 }
37043845 zig_unreachable();
37053846}
3847
3848TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, size_t size_in_bits) {
3849 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
3850 entry->type_ref = LLVMIntType(size_in_bits);
3851
3852 const char u_or_i = is_signed ? 'i' : 'u';
3853 buf_resize(&entry->name, 0);
3854 buf_appendf(&entry->name, "%c%zu", u_or_i, size_in_bits);
3855
3856 unsigned dwarf_tag;
3857 if (is_signed) {
3858 if (size_in_bits == 8) {
3859 dwarf_tag = ZigLLVMEncoding_DW_ATE_signed_char();
3860 } else {
3861 dwarf_tag = ZigLLVMEncoding_DW_ATE_signed();
3862 }
3863 } else {
3864 if (size_in_bits == 8) {
3865 dwarf_tag = ZigLLVMEncoding_DW_ATE_unsigned_char();
3866 } else {
3867 dwarf_tag = ZigLLVMEncoding_DW_ATE_unsigned();
3868 }
3869 }
3870
3871 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
3872 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
3873 entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
3874 debug_size_in_bits, debug_align_in_bits, dwarf_tag);
3875 entry->data.integral.is_signed = is_signed;
3876 entry->data.integral.bit_count = size_in_bits;
3877 return entry;
3878}
3879
3880uint32_t int_type_id_hash(IntTypeId x) {
3881 uint32_t hash = x.is_signed ? 2652528194 : 163929201;
3882 hash += ((uint32_t)x.bit_count) * 2998081557;
3883 return hash;
3884}
3885
3886bool int_type_id_eql(IntTypeId a, IntTypeId b) {
3887 return (a.is_signed == b.is_signed && a.bit_count == b.bit_count);
3888}
src/analyze.hpp+4-2
......@@ -18,8 +18,8 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
1818TypeTableEntry *get_pointer_to_type_volatile(CodeGen *g, TypeTableEntry *child_type, bool is_const, bool is_volatile);
1919bool is_node_void_expr(AstNode *node);
2020uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry);
21TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, size_t size_in_bits);
22TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, size_t size_in_bits);
21TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, uint8_t size_in_bits);
22TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, uint8_t size_in_bits);
2323TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
2424TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type);
2525TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry *child_type);
......@@ -143,4 +143,6 @@ ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_
143143
144144void init_const_undefined(CodeGen *g, ConstExprValue *const_val);
145145
146TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, size_t size_in_bits);
147
146148#endif
src/bignum.cpp+19-26
......@@ -46,42 +46,35 @@ void bignum_init_bignum(BigNum *dest, BigNum *src) {
4646 safe_memcpy(dest, src, 1);
4747}
4848
49static int u64_log2(uint64_t x) {
50 int result = 0;
51 for (; x != 0; x >>= 1) {
52 result += 1;
53 }
54 return result;
55}
56
4957bool bignum_fits_in_bits(BigNum *bn, int bit_count, bool is_signed) {
5058 assert(bn->kind == BigNumKindInt);
5159
5260 if (is_signed) {
53 if (bn->is_negative) {
54 if (bn->data.x_uint <= ((uint64_t)INT8_MAX) + 1) {
55 return bit_count >= 8;
56 } else if (bn->data.x_uint <= ((uint64_t)INT16_MAX) + 1) {
57 return bit_count >= 16;
58 } else if (bn->data.x_uint <= ((uint64_t)INT32_MAX) + 1) {
59 return bit_count >= 32;
60 } else {
61 return bit_count >= 64;
62 }
63 } else if (bn->data.x_uint <= (uint64_t)INT8_MAX) {
64 return bit_count >= 8;
65 } else if (bn->data.x_uint <= (uint64_t)INT16_MAX) {
66 return bit_count >= 16;
67 } else if (bn->data.x_uint <= (uint64_t)INT32_MAX) {
68 return bit_count >= 32;
61 uint64_t max_neg;
62 uint64_t max_pos;
63 if (bit_count < 64) {
64 max_neg = (1ULL << (bit_count - 1));
65 max_pos = max_neg - 1;
6966 } else {
70 return bit_count >= 64;
67 max_pos = ((uint64_t)INT64_MAX);
68 max_neg = max_pos + 1;
7169 }
70 uint64_t max_val = bn->is_negative ? max_neg : max_pos;
71 return bn->data.x_uint <= max_val;
7272 } else {
7373 if (bn->is_negative) {
7474 return bn->data.x_uint == 0;
7575 } else {
76 if (bn->data.x_uint <= UINT8_MAX) {
77 return bit_count >= 8;
78 } else if (bn->data.x_uint <= UINT16_MAX) {
79 return bit_count >= 16;
80 } else if (bn->data.x_uint <= UINT32_MAX) {
81 return bit_count >= 32;
82 } else {
83 return bit_count >= 64;
84 }
76 int required_bit_count = u64_log2(bn->data.x_uint);
77 return bit_count >= required_bit_count;
8578 }
8679 }
8780}
src/codegen.cpp+130-37
......@@ -58,6 +58,7 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
5858 g->import_table.init(32);
5959 g->builtin_fn_table.init(32);
6060 g->primitive_type_table.init(32);
61 g->int_type_table.init(8);
6162 g->fn_type_table.init(32);
6263 g->error_table.init(16);
6364 g->generic_table.init(16);
......@@ -232,6 +233,7 @@ void codegen_set_linker_script(CodeGen *g, const char *linker_script) {
232233
233234static void render_const_val(CodeGen *g, ConstExprValue *const_val);
234235static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name);
236static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val);
235237
236238static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
237239 if (fn_table_entry->llvm_value)
......@@ -2599,6 +2601,84 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s
25992601 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
26002602}
26012603
2604static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, ConstExprValue *const_val) {
2605 switch (const_val->special) {
2606 case ConstValSpecialRuntime:
2607 zig_unreachable();
2608 case ConstValSpecialUndef:
2609 return LLVMConstInt(big_int_type_ref, 0, false);
2610 case ConstValSpecialStatic:
2611 break;
2612 }
2613
2614 TypeTableEntry *canon_type = get_underlying_type(const_val->type);
2615 assert(!canon_type->zero_bits);
2616 switch (canon_type->id) {
2617 case TypeTableEntryIdInvalid:
2618 case TypeTableEntryIdVar:
2619 case TypeTableEntryIdMetaType:
2620 case TypeTableEntryIdUnreachable:
2621 case TypeTableEntryIdNumLitFloat:
2622 case TypeTableEntryIdNumLitInt:
2623 case TypeTableEntryIdUndefLit:
2624 case TypeTableEntryIdNullLit:
2625 case TypeTableEntryIdErrorUnion:
2626 case TypeTableEntryIdPureError:
2627 case TypeTableEntryIdEnum:
2628 case TypeTableEntryIdEnumTag:
2629 case TypeTableEntryIdTypeDecl:
2630 case TypeTableEntryIdNamespace:
2631 case TypeTableEntryIdBlock:
2632 case TypeTableEntryIdBoundFn:
2633 case TypeTableEntryIdArgTuple:
2634 case TypeTableEntryIdVoid:
2635 zig_unreachable();
2636 case TypeTableEntryIdBool:
2637 return LLVMConstInt(big_int_type_ref, const_val->data.x_bool ? 1 : 0, false);
2638 case TypeTableEntryIdInt:
2639 {
2640 LLVMValueRef int_val = gen_const_val(g, const_val);
2641 return LLVMConstZExt(int_val, big_int_type_ref);
2642 }
2643 return LLVMConstInt(big_int_type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false);
2644 case TypeTableEntryIdFloat:
2645 {
2646 LLVMValueRef float_val = gen_const_val(g, const_val);
2647 LLVMValueRef int_val = LLVMConstFPToUI(float_val, LLVMIntType(canon_type->data.floating.bit_count));
2648 return LLVMConstZExt(int_val, big_int_type_ref);
2649 }
2650 case TypeTableEntryIdPointer:
2651 case TypeTableEntryIdFn:
2652 case TypeTableEntryIdMaybe:
2653 {
2654 LLVMValueRef ptr_val = gen_const_val(g, const_val);
2655 LLVMValueRef ptr_size_int_val = LLVMConstPtrToInt(ptr_val, g->builtin_types.entry_usize->type_ref);
2656 return LLVMConstZExt(ptr_size_int_val, big_int_type_ref);
2657 }
2658 case TypeTableEntryIdArray:
2659 zig_panic("TODO bit pack an array");
2660 case TypeTableEntryIdUnion:
2661 zig_panic("TODO bit pack a union");
2662 case TypeTableEntryIdStruct:
2663 {
2664 assert(canon_type->data.structure.layout == ContainerLayoutPacked);
2665
2666 LLVMValueRef val = LLVMConstInt(big_int_type_ref, 0, false);
2667 for (size_t i = 0; i < canon_type->data.structure.src_field_count; i += 1) {
2668 TypeStructField *field = &canon_type->data.structure.fields[i];
2669 if (field->gen_index == SIZE_MAX) {
2670 continue;
2671 }
2672 LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, &const_val->data.x_struct.fields[i]);
2673 LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, field->packed_bits_size, false);
2674 val = LLVMConstShl(val, shift_amt);
2675 val = LLVMConstOr(val, child_val);
2676 }
2677 return val;
2678 }
2679 }
2680 zig_unreachable();
2681}
26022682
26032683static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
26042684 TypeTableEntry *canon_type = get_underlying_type(const_val->type);
......@@ -2670,15 +2750,57 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
26702750 case TypeTableEntryIdStruct:
26712751 {
26722752 LLVMValueRef *fields = allocate<LLVMValueRef>(canon_type->data.structure.gen_field_count);
2673 for (uint32_t i = 0; i < canon_type->data.structure.src_field_count; i += 1) {
2674 TypeStructField *type_struct_field = &canon_type->data.structure.fields[i];
2675 if (type_struct_field->gen_index == SIZE_MAX) {
2676 continue;
2753 size_t src_field_count = canon_type->data.structure.src_field_count;
2754 if (canon_type->data.structure.layout == ContainerLayoutPacked) {
2755 size_t src_field_index = 0;
2756 while (src_field_index < src_field_count) {
2757 TypeStructField *type_struct_field = &canon_type->data.structure.fields[src_field_index];
2758 if (type_struct_field->gen_index == SIZE_MAX) {
2759 src_field_index += 1;
2760 continue;
2761 }
2762
2763 size_t src_field_index_end = src_field_index + 1;
2764 for (; src_field_index_end < src_field_count; src_field_index_end += 1) {
2765 TypeStructField *it_field = &canon_type->data.structure.fields[src_field_index_end];
2766 if (it_field->gen_index != type_struct_field->gen_index)
2767 break;
2768 }
2769
2770 if (src_field_index + 1 == src_field_index_end) {
2771 fields[type_struct_field->gen_index] =
2772 gen_const_val(g, &const_val->data.x_struct.fields[src_field_index]);
2773 } else {
2774 LLVMTypeRef big_int_type_ref = LLVMStructGetTypeAtIndex(canon_type->type_ref,
2775 type_struct_field->gen_index);
2776 LLVMValueRef val = LLVMConstInt(big_int_type_ref, 0, false);
2777 for (size_t i = src_field_index; i < src_field_index_end; i += 1) {
2778 TypeStructField *it_field = &canon_type->data.structure.fields[i];
2779 if (it_field->gen_index == SIZE_MAX) {
2780 continue;
2781 }
2782 LLVMValueRef child_val = pack_const_int(g, big_int_type_ref,
2783 &const_val->data.x_struct.fields[i]);
2784 LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref,
2785 it_field->packed_bits_size, false);
2786 val = LLVMConstShl(val, shift_amt);
2787 val = LLVMConstOr(val, child_val);
2788 }
2789 fields[type_struct_field->gen_index] = val;
2790 }
2791
2792 src_field_index = src_field_index_end;
2793 }
2794 } else {
2795 for (uint32_t i = 0; i < src_field_count; i += 1) {
2796 TypeStructField *type_struct_field = &canon_type->data.structure.fields[i];
2797 if (type_struct_field->gen_index == SIZE_MAX) {
2798 continue;
2799 }
2800 fields[type_struct_field->gen_index] = gen_const_val(g, &const_val->data.x_struct.fields[i]);
26772801 }
2678 fields[type_struct_field->gen_index] = gen_const_val(g, &const_val->data.x_struct.fields[i]);
26792802 }
2680 return LLVMConstNamedStruct(canon_type->type_ref, fields,
2681 canon_type->data.structure.gen_field_count);
2803 return LLVMConstNamedStruct(canon_type->type_ref, fields, canon_type->data.structure.gen_field_count);
26822804 }
26832805 case TypeTableEntryIdUnion:
26842806 {
......@@ -3406,37 +3528,8 @@ static void define_builtin_types(CodeGen *g) {
34063528 size_t size_in_bits = int_sizes_in_bits[int_size_i];
34073529 for (size_t is_sign_i = 0; is_sign_i < array_length(is_signed_list); is_sign_i += 1) {
34083530 bool is_signed = is_signed_list[is_sign_i];
3409
3410 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
3411 entry->type_ref = LLVMIntType(size_in_bits);
3412
3413 const char u_or_i = is_signed ? 'i' : 'u';
3414 buf_resize(&entry->name, 0);
3415 buf_appendf(&entry->name, "%c%zu", u_or_i, size_in_bits);
3416
3417 unsigned dwarf_tag;
3418 if (is_signed) {
3419 if (size_in_bits == 8) {
3420 dwarf_tag = ZigLLVMEncoding_DW_ATE_signed_char();
3421 } else {
3422 dwarf_tag = ZigLLVMEncoding_DW_ATE_signed();
3423 }
3424 } else {
3425 if (size_in_bits == 8) {
3426 dwarf_tag = ZigLLVMEncoding_DW_ATE_unsigned_char();
3427 } else {
3428 dwarf_tag = ZigLLVMEncoding_DW_ATE_unsigned();
3429 }
3430 }
3431
3432 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
3433 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
3434 entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
3435 debug_size_in_bits, debug_align_in_bits, dwarf_tag);
3436 entry->data.integral.is_signed = is_signed;
3437 entry->data.integral.bit_count = size_in_bits;
3531 TypeTableEntry *entry = make_int_type(g, is_signed, size_in_bits);
34383532 g->primitive_type_table.put(&entry->name, entry);
3439
34403533 get_int_type_ptr(g, is_signed, size_in_bits)[0] = entry;
34413534 }
34423535 }
test/run_tests.cpp+2
......@@ -2212,6 +2212,7 @@ static void run_all_tests(bool reverse) {
22122212 for (size_t i = test_cases.length;;) {
22132213 TestCase *test_case = test_cases.at(i);
22142214 printf("Test %zu/%zu %s...", i + 1, test_cases.length, test_case->case_name);
2215 fflush(stdout);
22152216 run_test(test_case);
22162217 printf("OK\n");
22172218 if (i == 0) break;
......@@ -2221,6 +2222,7 @@ static void run_all_tests(bool reverse) {
22212222 for (size_t i = 0; i < test_cases.length; i += 1) {
22222223 TestCase *test_case = test_cases.at(i);
22232224 printf("Test %zu/%zu %s...", i + 1, test_cases.length, test_case->case_name);
2225 fflush(stdout);
22242226 run_test(test_case);
22252227 printf("OK\n");
22262228 }