فهرست منبع

`map` immutable fields: count, capacity, allocator

Ginger Bill 8 سال پیش
والد
کامیت
5796c41357
4فایلهای تغییر یافته به همراه143 افزوده شده و 10 حذف شده
  1. 7 4
      core/fmt.odin
  2. 84 2
      src/gb/gb.h
  3. 17 3
      src/ir.c
  4. 35 1
      src/types.c

+ 7 - 4
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, " -> ");

+ 84 - 2
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 <stdio.h>
+
+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

+ 17 - 3
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;
 

+ 35 - 1
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) {