From 5796c413571140798d9ca597cda4d34c6762eabe Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Mon, 6 Feb 2017 22:53:48 +0000 Subject: [PATCH] `map` immutable fields: count, capacity, allocator --- core/fmt.odin | 11 ++++--- src/gb/gb.h | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/ir.c | 20 ++++++++++-- src/types.c | 36 ++++++++++++++++++++- 4 files changed, 143 insertions(+), 10 deletions(-) diff --git a/core/fmt.odin b/core/fmt.odin index 1de2c2293..105888caf 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -142,10 +142,13 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { if info.params == nil { buffer_write_string(buf, "()"); } else { - count := (cast(^Tuple)info.params).fields.count; - if count == 1 { buffer_write_string(buf, "("); } - buffer_write_type(buf, info.params); - if count == 1 { buffer_write_string(buf, ")"); } + fields := (cast(^Tuple)info.params).fields; + buffer_write_string(buf, "("); + for f, i in fields { + if i > 0 { buffer_write_string(buf, ", "); } + buffer_write_type(buf, f.type_info); + } + buffer_write_string(buf, ")"); } if info.results != nil { buffer_write_string(buf, " -> "); diff --git a/src/gb/gb.h b/src/gb/gb.h index 8edd4b92f..e45ceb050 100644 --- a/src/gb/gb.h +++ b/src/gb/gb.h @@ -58,6 +58,7 @@ TODOS - More date & time functions VERSION HISTORY + 0.27 - OSX fixes and Linux gbAffinity 0.26d - Minor changes to how gbFile works 0.26c - gb_str_to_f* fix 0.26b - Minor fixes @@ -1008,7 +1009,12 @@ typedef struct gbAffinity { } gbAffinity; #elif defined(GB_SYSTEM_LINUX) -#error TODO(bill): Implement gbAffinity for linux +typedef struct gbAffinity { + b32 is_accurate; + isize core_count; + isize thread_count; + isize threads_per_core; +} gbAffinity; #else #error TODO(bill): Unknown system #endif @@ -4979,7 +4985,83 @@ isize gb_affinity_thread_count_for_core(gbAffinity *a, isize core) { } #elif defined(GB_SYSTEM_LINUX) -#error TODO(bill): Implement gbAffinity for linux +// IMPORTANT TODO(bill): This gbAffinity stuff for linux needs be improved a lot! +// NOTE(zangent): I have to read /proc/cpuinfo to get the number of threads per core. +#include + +void gb_affinity_init(gbAffinity *a) { + b32 accurate = true; + isize threads = 0; + + a->thread_count = 1; + a->core_count = sysconf(_SC_NPROCESSORS_ONLN); + a->threads_per_core = 1; + + + if(a->core_count <= 0) { + a->core_count = 1; + accurate = false; + } + + // Parsing /proc/cpuinfo to get the number of threads per core. + // NOTE(zangent): This calls the CPU's threads "cores", although the wording + // is kind of weird. This should be right, though. + if (fopen("/proc/cpuinfo", "r") != NULL) { + for (;;) { + // The 'temporary char'. Everything goes into this char, + // so that we can check against EOF at the end of this loop. + char c; + +#define AF__CHECK(letter) ((c = getc(cpu_info)) == letter) + if (AF__CHECK('c') && AF__CHECK('p') && AF__CHECK('u') && AF__CHECK(' ') && + AF__CHECK('c') && AF__CHECK('o') && AF__CHECK('r') && AF__CHECK('e') && AF__CHECK('s')) { + // We're on a CPU info line. + while (!AF__CHECK(EOF)) { + if (c == '\n') { + break; + } else if (c < '0' || '9' > c) { + continue; + } + threads = threads * 10 + (c - '0'); + } + break; + } else { + while (!AF__CHECK('\n')) { + if (c==EOF) { + break; + } + } + } + if (c == EOF) { + break; + } +#undef AF__CHECK + } + } + + if (threads == 0) { + threads = 1; + accurate = false; + } + + a->threads_per_core = threads; + a->thread_count = a->threads_per_core * a->core_count; + a->is_accurate = accurate; + +} + +void gb_affinity_destroy(gbAffinity *a) { + gb_unused(a); +} + +b32 gb_affinity_set(gbAffinity *a, isize core, isize thread_index) { + return true; +} + +isize gb_affinity_thread_count_for_core(gbAffinity *a, isize core) { + GB_ASSERT(0 <= core && core < a->core_count); + return a->threads_per_core; +} #else #error TODO(bill): Unknown system #endif diff --git a/src/ir.c b/src/ir.c index c7d97fd15..c6c834068 100644 --- a/src/ir.c +++ b/src/ir.c @@ -1495,7 +1495,7 @@ Type *ir_addr_type(irAddr addr) { return type_deref(t); } -irValue *ir_insert_map_key_and_value(irProcedure *proc, irValue *addr, Type *map_type, +irValue *ir_insert_dynamic_map_key_and_value(irProcedure *proc, irValue *addr, Type *map_type, irValue *map_key, irValue *map_value) { map_type = base_type(map_type); @@ -1519,7 +1519,7 @@ irValue *ir_addr_store(irProcedure *proc, irAddr addr, irValue *value) { return NULL; } if (addr.kind == irAddr_Map) { - return ir_insert_map_key_and_value(proc, addr.addr, addr.map_type, addr.map_key, value); + return ir_insert_dynamic_map_key_and_value(proc, addr.addr, addr.map_type, addr.map_key, value); } irValue *v = ir_emit_conv(proc, value, ir_addr_type(addr)); @@ -1925,6 +1925,13 @@ irValue *ir_emit_deep_field_gep(irProcedure *proc, Type *type, irValue *e, Selec e = ir_emit_array_epi(proc, e, index); } else if (type->kind == Type_Array) { e = ir_emit_array_epi(proc, e, index); + } else if (type->kind == Type_Map) { + e = ir_emit_struct_ep(proc, e, 1); + switch (index) { + case 0: e = ir_emit_struct_ep(proc, e, 1); break; // count + case 1: e = ir_emit_struct_ep(proc, e, 2); break; // capacity + case 2: e = ir_emit_struct_ep(proc, e, 3); break; // allocator + } } else { GB_PANIC("un-gep-able type"); } @@ -1951,6 +1958,13 @@ irValue *ir_emit_deep_field_ev(irProcedure *proc, Type *type, irValue *e, Select GB_PANIC("TODO(bill): IS THIS EVEN CORRECT?"); type = type->Record.fields[index]->type; e = ir_emit_conv(proc, e, type); + } else if (type->kind == Type_Map) { + e = ir_emit_struct_ev(proc, e, 1); + switch (index) { + case 0: e = ir_emit_struct_ev(proc, e, 1); break; // count + case 1: e = ir_emit_struct_ev(proc, e, 2); break; // capacity + case 2: e = ir_emit_struct_ev(proc, e, 3); break; // allocator + } } else { e = ir_emit_struct_ev(proc, e, index); } @@ -4192,7 +4206,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { irValue *key = ir_build_expr(proc, fv->field); irValue *value = ir_build_expr(proc, fv->value); - ir_insert_map_key_and_value(proc, v, type, key, value); + ir_insert_dynamic_map_key_and_value(proc, v, type, key, value); } } break; diff --git a/src/types.c b/src/types.c index 0402b2470..be28c82f0 100644 --- a/src/types.c +++ b/src/types.c @@ -1073,6 +1073,10 @@ gb_global Entity *entity__dynamic_array_count = NULL; gb_global Entity *entity__dynamic_array_capacity = NULL; gb_global Entity *entity__dynamic_array_allocator = NULL; +gb_global Entity *entity__dynamic_map_count = NULL; +gb_global Entity *entity__dynamic_map_capacity = NULL; +gb_global Entity *entity__dynamic_map_allocator = NULL; + Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_name, bool is_type, Selection sel); Selection lookup_field(gbAllocator a, Type *type_, String field_name, bool is_type) { @@ -1240,7 +1244,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n sel.entity = entity__slice_count; return sel; } - } else if (type->kind == Type_DynamicArray) { + } else if (type->kind == Type_DynamicArray) { String data_str = str_lit("data"); String count_str = str_lit("count"); String capacity_str = str_lit("capacity"); @@ -1273,6 +1277,36 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n sel.entity = entity__dynamic_array_allocator; return sel; } + } else if (type->kind == Type_Map) { + String count_str = str_lit("count"); + String capacity_str = str_lit("capacity"); + String allocator_str = str_lit("allocator"); + + if (str_eq(field_name, count_str)) { + selection_add_index(&sel, 0); + if (entity__dynamic_map_count == NULL) { + entity__dynamic_map_count = make_entity_field(a, NULL, make_token_ident(count_str), t_int, false, 0); + entity__dynamic_map_count->Variable.is_immutable = true; + } + sel.entity = entity__dynamic_map_count; + return sel; + } else if (str_eq(field_name, capacity_str)) { + selection_add_index(&sel, 1); + if (entity__dynamic_map_capacity == NULL) { + entity__dynamic_map_capacity = make_entity_field(a, NULL, make_token_ident(capacity_str), t_int, false, 1); + entity__dynamic_map_capacity->Variable.is_immutable = true; + } + sel.entity = entity__dynamic_map_capacity; + return sel; + } else if (str_eq(field_name, allocator_str)) { + selection_add_index(&sel, 2); + if (entity__dynamic_map_allocator == NULL) { + entity__dynamic_map_allocator = make_entity_field(a, NULL, make_token_ident(allocator_str), t_allocator, false, 2); + entity__dynamic_map_allocator->Variable.is_immutable = true; + } + sel.entity = entity__dynamic_map_allocator; + return sel; + } } if (type->kind != Type_Record) {