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 {...@@ -873,11 +873,13 @@ struct TypeStructField {
873 TypeTableEntry *type_entry;873 TypeTableEntry *type_entry;
874 size_t src_index;874 size_t src_index;
875 size_t gen_index;875 size_t gen_index;
876 // offset from the memory at gen_index
877 size_t packed_bits_offset;
878 size_t packed_bits_size;
876};879};
877struct TypeTableEntryStruct {880struct TypeTableEntryStruct {
878 AstNode *decl_node;881 AstNode *decl_node;
879 ContainerLayout layout;882 ContainerLayout layout;
880 bool is_packed;
881 uint32_t src_field_count;883 uint32_t src_field_count;
882 uint32_t gen_field_count;884 uint32_t gen_field_count;
883 TypeStructField *fields;885 TypeStructField *fields;
...@@ -1037,7 +1039,7 @@ struct TypeTableEntry {...@@ -1037,7 +1039,7 @@ struct TypeTableEntry {
10371039
1038 // use these fields to make sure we don't duplicate type table entries for the same type1040 // use these fields to make sure we don't duplicate type table entries for the same type
1039 TypeTableEntry *pointer_parent[2][2]; // [0 - mut, 1 - const][0 - normal, 1 - volatile]1041 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]
1041 HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size;1043 HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size;
1042 TypeTableEntry *maybe_parent;1044 TypeTableEntry *maybe_parent;
1043 TypeTableEntry *error_parent;1045 TypeTableEntry *error_parent;
...@@ -1193,6 +1195,14 @@ enum PanicMsgId {...@@ -1193,6 +1195,14 @@ enum PanicMsgId {
1193uint32_t fn_eval_hash(Scope*);1195uint32_t fn_eval_hash(Scope*);
1194bool fn_eval_eql(Scope *a, Scope *b);1196bool 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
1196struct CodeGen {1206struct CodeGen {
1197 LLVMModuleRef module;1207 LLVMModuleRef module;
1198 ZigList<ErrorMsg*> errors;1208 ZigList<ErrorMsg*> errors;
...@@ -1208,6 +1218,7 @@ struct CodeGen {...@@ -1208,6 +1218,7 @@ struct CodeGen {
1208 HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;1218 HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;
1209 HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;1219 HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;
1210 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table;1220 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;
1211 HashMap<FnTypeId *, TypeTableEntry *, fn_type_id_hash, fn_type_id_eql> fn_type_table;1222 HashMap<FnTypeId *, TypeTableEntry *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
1212 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;1223 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
1213 HashMap<GenericFnTypeId *, FnTableEntry *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;1224 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) {...@@ -261,6 +261,24 @@ uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry) {
261 }261 }
262}262}
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
264static bool is_slice(TypeTableEntry *type) {282static bool is_slice(TypeTableEntry *type) {
265 return type->id == TypeTableEntryIdStruct && type->data.structure.is_slice;283 return type->id == TypeTableEntryIdStruct && type->data.structure.is_slice;
266}284}
...@@ -507,7 +525,7 @@ static void slice_type_common_init(CodeGen *g, TypeTableEntry *child_type,...@@ -507,7 +525,7 @@ static void slice_type_common_init(CodeGen *g, TypeTableEntry *child_type,
507 TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const);525 TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const);
508526
509 unsigned element_count = 2;527 unsigned element_count = 2;
510 entry->data.structure.is_packed = false;528 entry->data.structure.layout = ContainerLayoutAuto;
511 entry->data.structure.is_slice = true;529 entry->data.structure.is_slice = true;
512 entry->data.structure.src_field_count = element_count;530 entry->data.structure.src_field_count = element_count;
513 entry->data.structure.gen_field_count = element_count;531 entry->data.structure.gen_field_count = element_count;
...@@ -531,7 +549,7 @@ static void slice_type_common_init(CodeGen *g, TypeTableEntry *child_type,...@@ -531,7 +549,7 @@ static void slice_type_common_init(CodeGen *g, TypeTableEntry *child_type,
531549
532TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {550TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {
533 assert(child_type->id != TypeTableEntryIdInvalid);551 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
536 if (*parent_pointer) {554 if (*parent_pointer) {
537 return *parent_pointer;555 return *parent_pointer;
...@@ -1269,6 +1287,48 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {...@@ -1269,6 +1287,48 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
1269 }1287 }
1270}1288}
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
1272static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {1332static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
1273 // if you change the logic of this function likely you must make a similar change in1333 // if you change the logic of this function likely you must make a similar change in
1274 // parseh.cpp1334 // parseh.cpp
...@@ -1307,22 +1367,77 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {...@@ -1307,22 +1367,77 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
13071367
1308 Scope *scope = &struct_type->data.structure.decls_scope->base;1368 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
1310 for (size_t i = 0; i < field_count; i += 1) {1376 for (size_t i = 0; i < field_count; i += 1) {
1311 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];1377 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
1312 TypeTableEntry *field_type = type_struct_field->type_entry;1378 TypeTableEntry *field_type = type_struct_field->type_entry;
13131379
1314 ensure_complete_type(g, field_type);1380 ensure_complete_type(g, field_type);
1381
1315 if (type_is_invalid(field_type)) {1382 if (type_is_invalid(field_type)) {
1316 struct_type->data.structure.is_invalid = true;1383 struct_type->data.structure.is_invalid = true;
1317 continue;1384 break;
1318 }1385 }
13191386
1320 if (!type_has_bits(field_type))1387 if (!type_has_bits(field_type))
1321 continue;1388 continue;
13221389
1323 element_types[type_struct_field->gen_index] = field_type->type_ref;1390 type_struct_field->gen_index = gen_field_index;
1324 assert(element_types[type_struct_field->gen_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;
1325 }1434 }
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
1326 struct_type->data.structure.embedded_in_current = false;1441 struct_type->data.structure.embedded_in_current = false;
1327 struct_type->data.structure.complete = true;1442 struct_type->data.structure.complete = true;
13281443
...@@ -1337,13 +1452,18 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {...@@ -1337,13 +1452,18 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
1337 }1452 }
1338 assert(struct_type->di_type);1453 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
1341 LLVMStructSetBody(struct_type->type_ref, element_types, gen_field_count, packed);1460 LLVMStructSetBody(struct_type->type_ref, element_types, gen_field_count, packed);
1342 assert(LLVMStoreSizeOfType(g->target_data_ref, struct_type->type_ref) > 0);1461 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
1346 ImportTableEntry *import = get_scope_import(scope);1465 ImportTableEntry *import = get_scope_import(scope);
1466 size_t debug_field_index = 0;
1347 for (size_t i = 0; i < field_count; i += 1) {1467 for (size_t i = 0; i < field_count; i += 1) {
1348 AstNode *field_node = decl_node->data.container_decl.fields.at(i);1468 AstNode *field_node = decl_node->data.container_decl.fields.at(i);
1349 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];1469 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
...@@ -1369,19 +1489,28 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {...@@ -1369,19 +1489,28 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
1369 assert(field_type->type_ref);1489 assert(field_type->type_ref);
1370 assert(struct_type->type_ref);1490 assert(struct_type->type_ref);
1371 assert(struct_type->data.structure.complete);1491 assert(struct_type->data.structure.complete);
1372 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref);1492 uint64_t debug_size_in_bits;
1373 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, field_type->type_ref);1493 uint64_t debug_align_in_bits;
1374 uint64_t debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref,1494 uint64_t debug_offset_in_bits;
1375 gen_field_index);1495 if (packed) {
1376 di_element_types[gen_field_index] = ZigLLVMCreateDebugMemberType(g->dbuilder,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,
1377 ZigLLVMTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name),1506 ZigLLVMTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name),
1378 import->di_file, field_node->line + 1,1507 import->di_file, field_node->line + 1,
1379 debug_size_in_bits,1508 debug_size_in_bits,
1380 debug_align_in_bits,1509 debug_align_in_bits,
1381 debug_offset_in_bits,1510 debug_offset_in_bits,
1382 0, field_di_type);1511 0, field_di_type);
13831512 assert(di_element_types[debug_field_index]);
1384 assert(di_element_types[gen_field_index]);1513 debug_field_index += 1;
1385 }1514 }
13861515
13871516
...@@ -1393,7 +1522,7 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {...@@ -1393,7 +1522,7 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
1393 import->di_file, decl_node->line + 1,1522 import->di_file, decl_node->line + 1,
1394 debug_size_in_bits,1523 debug_size_in_bits,
1395 debug_align_in_bits,1524 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
1398 ZigLLVMReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type);1527 ZigLLVMReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type);
1399 struct_type->di_type = replacement_di_type;1528 struct_type->di_type = replacement_di_type;
...@@ -2672,7 +2801,7 @@ bool is_node_void_expr(AstNode *node) {...@@ -2672,7 +2801,7 @@ bool is_node_void_expr(AstNode *node) {
2672 return false;2801 return false;
2673}2802}
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) {
2676 size_t index;2805 size_t index;
2677 if (size_in_bits == 8) {2806 if (size_in_bits == 8) {
2678 index = 0;2807 index = 0;
...@@ -2683,13 +2812,25 @@ TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, size_t size_in_bit...@@ -2683,13 +2812,25 @@ TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, size_t size_in_bit
2683 } else if (size_in_bits == 64) {2812 } else if (size_in_bits == 64) {
2684 index = 3;2813 index = 3;
2685 } else {2814 } else {
2686 zig_unreachable();2815 return nullptr;
2687 }2816 }
2688 return &g->builtin_types.entry_int[is_signed ? 0 : 1][index];2817 return &g->builtin_types.entry_int[is_signed ? 0 : 1][index];
2689}2818}
26902819
2691TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, size_t size_in_bits) {2820TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, uint8_t size_in_bits) {
2692 return *get_int_type_ptr(g, is_signed, 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;
2693}2834}
26942835
2695TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) {2836TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) {
...@@ -3703,3 +3844,45 @@ void render_const_value(Buf *buf, ConstExprValue *const_val) {...@@ -3703,3 +3844,45 @@ void render_const_value(Buf *buf, ConstExprValue *const_val) {
3703 }3844 }
3704 zig_unreachable();3845 zig_unreachable();
3705}3846}
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...@@ -18,8 +18,8 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
18TypeTableEntry *get_pointer_to_type_volatile(CodeGen *g, TypeTableEntry *child_type, bool is_const, bool is_volatile);18TypeTableEntry *get_pointer_to_type_volatile(CodeGen *g, TypeTableEntry *child_type, bool is_const, bool is_volatile);
19bool is_node_void_expr(AstNode *node);19bool is_node_void_expr(AstNode *node);
20uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry);20uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry);
21TypeTableEntry **get_int_type_ptr(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, size_t size_in_bits);22TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, uint8_t size_in_bits);
23TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);23TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
24TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type);24TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type);
25TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry *child_type);25TypeTableEntry *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_...@@ -143,4 +143,6 @@ ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_
143143
144void init_const_undefined(CodeGen *g, ConstExprValue *const_val);144void init_const_undefined(CodeGen *g, ConstExprValue *const_val);
145145
146TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, size_t size_in_bits);
147
146#endif148#endif
src/bignum.cpp+19-26
...@@ -46,42 +46,35 @@ void bignum_init_bignum(BigNum *dest, BigNum *src) {...@@ -46,42 +46,35 @@ void bignum_init_bignum(BigNum *dest, BigNum *src) {
46 safe_memcpy(dest, src, 1);46 safe_memcpy(dest, src, 1);
47}47}
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
49bool bignum_fits_in_bits(BigNum *bn, int bit_count, bool is_signed) {57bool bignum_fits_in_bits(BigNum *bn, int bit_count, bool is_signed) {
50 assert(bn->kind == BigNumKindInt);58 assert(bn->kind == BigNumKindInt);
5159
52 if (is_signed) {60 if (is_signed) {
53 if (bn->is_negative) {61 uint64_t max_neg;
54 if (bn->data.x_uint <= ((uint64_t)INT8_MAX) + 1) {62 uint64_t max_pos;
55 return bit_count >= 8;63 if (bit_count < 64) {
56 } else if (bn->data.x_uint <= ((uint64_t)INT16_MAX) + 1) {64 max_neg = (1ULL << (bit_count - 1));
57 return bit_count >= 16;65 max_pos = max_neg - 1;
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;
69 } else {66 } else {
70 return bit_count >= 64;67 max_pos = ((uint64_t)INT64_MAX);
68 max_neg = max_pos + 1;
71 }69 }
70 uint64_t max_val = bn->is_negative ? max_neg : max_pos;
71 return bn->data.x_uint <= max_val;
72 } else {72 } else {
73 if (bn->is_negative) {73 if (bn->is_negative) {
74 return bn->data.x_uint == 0;74 return bn->data.x_uint == 0;
75 } else {75 } else {
76 if (bn->data.x_uint <= UINT8_MAX) {76 int required_bit_count = u64_log2(bn->data.x_uint);
77 return bit_count >= 8;77 return bit_count >= required_bit_count;
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 }
85 }78 }
86 }79 }
87}80}
src/codegen.cpp+130-37
...@@ -58,6 +58,7 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {...@@ -58,6 +58,7 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
58 g->import_table.init(32);58 g->import_table.init(32);
59 g->builtin_fn_table.init(32);59 g->builtin_fn_table.init(32);
60 g->primitive_type_table.init(32);60 g->primitive_type_table.init(32);
61 g->int_type_table.init(8);
61 g->fn_type_table.init(32);62 g->fn_type_table.init(32);
62 g->error_table.init(16);63 g->error_table.init(16);
63 g->generic_table.init(16);64 g->generic_table.init(16);
...@@ -232,6 +233,7 @@ void codegen_set_linker_script(CodeGen *g, const char *linker_script) {...@@ -232,6 +233,7 @@ void codegen_set_linker_script(CodeGen *g, const char *linker_script) {
232233
233static void render_const_val(CodeGen *g, ConstExprValue *const_val);234static void render_const_val(CodeGen *g, ConstExprValue *const_val);
234static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name);235static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name);
236static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val);
235237
236static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {238static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
237 if (fn_table_entry->llvm_value)239 if (fn_table_entry->llvm_value)
...@@ -2599,6 +2601,84 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s...@@ -2599,6 +2601,84 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s
2599 return LLVMConstInBoundsGEP(base_ptr, indices, 2);2601 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
2600}2602}
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
2603static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {2683static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
2604 TypeTableEntry *canon_type = get_underlying_type(const_val->type);2684 TypeTableEntry *canon_type = get_underlying_type(const_val->type);
...@@ -2670,15 +2750,57 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {...@@ -2670,15 +2750,57 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
2670 case TypeTableEntryIdStruct:2750 case TypeTableEntryIdStruct:
2671 {2751 {
2672 LLVMValueRef *fields = allocate<LLVMValueRef>(canon_type->data.structure.gen_field_count);2752 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) {2753 size_t src_field_count = canon_type->data.structure.src_field_count;
2674 TypeStructField *type_struct_field = &canon_type->data.structure.fields[i];2754 if (canon_type->data.structure.layout == ContainerLayoutPacked) {
2675 if (type_struct_field->gen_index == SIZE_MAX) {2755 size_t src_field_index = 0;
2676 continue;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]);
2677 }2801 }
2678 fields[type_struct_field->gen_index] = gen_const_val(g, &const_val->data.x_struct.fields[i]);
2679 }2802 }
2680 return LLVMConstNamedStruct(canon_type->type_ref, fields,2803 return LLVMConstNamedStruct(canon_type->type_ref, fields, canon_type->data.structure.gen_field_count);
2681 canon_type->data.structure.gen_field_count);
2682 }2804 }
2683 case TypeTableEntryIdUnion:2805 case TypeTableEntryIdUnion:
2684 {2806 {
...@@ -3406,37 +3528,8 @@ static void define_builtin_types(CodeGen *g) {...@@ -3406,37 +3528,8 @@ static void define_builtin_types(CodeGen *g) {
3406 size_t size_in_bits = int_sizes_in_bits[int_size_i];3528 size_t size_in_bits = int_sizes_in_bits[int_size_i];
3407 for (size_t is_sign_i = 0; is_sign_i < array_length(is_signed_list); is_sign_i += 1) {3529 for (size_t is_sign_i = 0; is_sign_i < array_length(is_signed_list); is_sign_i += 1) {
3408 bool is_signed = is_signed_list[is_sign_i];3530 bool is_signed = is_signed_list[is_sign_i];
34093531 TypeTableEntry *entry = make_int_type(g, is_signed, size_in_bits);
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;
3438 g->primitive_type_table.put(&entry->name, entry);3532 g->primitive_type_table.put(&entry->name, entry);
3439
3440 get_int_type_ptr(g, is_signed, size_in_bits)[0] = entry;3533 get_int_type_ptr(g, is_signed, size_in_bits)[0] = entry;
3441 }3534 }
3442 }3535 }
test/run_tests.cpp+2
...@@ -2212,6 +2212,7 @@ static void run_all_tests(bool reverse) {...@@ -2212,6 +2212,7 @@ static void run_all_tests(bool reverse) {
2212 for (size_t i = test_cases.length;;) {2212 for (size_t i = test_cases.length;;) {
2213 TestCase *test_case = test_cases.at(i);2213 TestCase *test_case = test_cases.at(i);
2214 printf("Test %zu/%zu %s...", i + 1, test_cases.length, test_case->case_name);2214 printf("Test %zu/%zu %s...", i + 1, test_cases.length, test_case->case_name);
2215 fflush(stdout);
2215 run_test(test_case);2216 run_test(test_case);
2216 printf("OK\n");2217 printf("OK\n");
2217 if (i == 0) break;2218 if (i == 0) break;
...@@ -2221,6 +2222,7 @@ static void run_all_tests(bool reverse) {...@@ -2221,6 +2222,7 @@ static void run_all_tests(bool reverse) {
2221 for (size_t i = 0; i < test_cases.length; i += 1) {2222 for (size_t i = 0; i < test_cases.length; i += 1) {
2222 TestCase *test_case = test_cases.at(i);2223 TestCase *test_case = test_cases.at(i);
2223 printf("Test %zu/%zu %s...", i + 1, test_cases.length, test_case->case_name);2224 printf("Test %zu/%zu %s...", i + 1, test_cases.length, test_case->case_name);
2225 fflush(stdout);
2224 run_test(test_case);2226 run_test(test_case);
2225 printf("OK\n");2227 printf("OK\n");
2226 }2228 }