core.odin 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  1. // This is the runtime code required by the compiler
  2. // IMPORTANT NOTE(bill): Do not change the order of any of this data
  3. // The compiler relies upon this _exact_ order
  4. package runtime
  5. import "core:os"
  6. import "core:mem"
  7. // Naming Conventions:
  8. // In general, Ada_Case for types and snake_case for values
  9. //
  10. // Package Name: snake_case (but prefer single word)
  11. // Import Name: snake_case (but prefer single word)
  12. // Types: Ada_Case
  13. // Enum Values: Ada_Case
  14. // Procedures: snake_case
  15. // Local Variables: snake_case
  16. // Constant Variables: SCREAMING_SNAKE_CASE
  17. // IMPORTANT NOTE(bill): `type_info_of` cannot be used within a
  18. // #shared_global_scope due to the internals of the compiler.
  19. // This could change at a later date if the all these data structures are
  20. // implemented within the compiler rather than in this "preload" file
  21. // NOTE(bill): This must match the compiler's
  22. Calling_Convention :: enum {
  23. Invalid = 0,
  24. Odin = 1,
  25. Contextless = 2,
  26. C = 3,
  27. Std = 4,
  28. Fast = 5,
  29. }
  30. Type_Info_Enum_Value :: union {
  31. rune,
  32. i8, i16, i32, i64, int,
  33. u8, u16, u32, u64, uint, uintptr,
  34. };
  35. // Variant Types
  36. Type_Info_Named :: struct {name: string, base: ^Type_Info};
  37. Type_Info_Integer :: struct {signed: bool};
  38. Type_Info_Rune :: struct {};
  39. Type_Info_Float :: struct {};
  40. Type_Info_Complex :: struct {};
  41. Type_Info_String :: struct {is_cstring: bool};
  42. Type_Info_Boolean :: struct {};
  43. Type_Info_Any :: struct {};
  44. Type_Info_Type_Id :: struct {};
  45. Type_Info_Pointer :: struct {
  46. elem: ^Type_Info // nil -> rawptr
  47. };
  48. Type_Info_Procedure :: struct {
  49. params: ^Type_Info, // Type_Info_Tuple
  50. results: ^Type_Info, // Type_Info_Tuple
  51. variadic: bool,
  52. convention: Calling_Convention,
  53. };
  54. Type_Info_Array :: struct {
  55. elem: ^Type_Info,
  56. elem_size: int,
  57. count: int,
  58. };
  59. Type_Info_Dynamic_Array :: struct {elem: ^Type_Info, elem_size: int};
  60. Type_Info_Slice :: struct {elem: ^Type_Info, elem_size: int};
  61. Type_Info_Tuple :: struct { // Only really used for procedures
  62. types: []^Type_Info,
  63. names: []string,
  64. };
  65. Type_Info_Struct :: struct {
  66. types: []^Type_Info,
  67. names: []string,
  68. offsets: []uintptr, // offsets may not be used in tuples
  69. usings: []bool, // usings may not be used in tuples
  70. is_packed: bool,
  71. is_raw_union: bool,
  72. custom_align: bool,
  73. };
  74. Type_Info_Union :: struct {
  75. variants: []^Type_Info,
  76. tag_offset: uintptr,
  77. tag_type: ^Type_Info,
  78. };
  79. Type_Info_Enum :: struct {
  80. base: ^Type_Info,
  81. names: []string,
  82. values: []Type_Info_Enum_Value,
  83. };
  84. Type_Info_Map :: struct {
  85. key: ^Type_Info,
  86. value: ^Type_Info,
  87. generated_struct: ^Type_Info,
  88. };
  89. Type_Info_Bit_Field :: struct {
  90. names: []string,
  91. bits: []i32,
  92. offsets: []i32,
  93. };
  94. Type_Info_Bit_Set :: struct {
  95. elem: ^Type_Info,
  96. underlying: ^Type_Info, // Possibly nil
  97. lower: i64,
  98. upper: i64,
  99. };
  100. Type_Info :: struct {
  101. size: int,
  102. align: int,
  103. id: typeid,
  104. variant: union {
  105. Type_Info_Named,
  106. Type_Info_Integer,
  107. Type_Info_Rune,
  108. Type_Info_Float,
  109. Type_Info_Complex,
  110. Type_Info_String,
  111. Type_Info_Boolean,
  112. Type_Info_Any,
  113. Type_Info_Type_Id,
  114. Type_Info_Pointer,
  115. Type_Info_Procedure,
  116. Type_Info_Array,
  117. Type_Info_Dynamic_Array,
  118. Type_Info_Slice,
  119. Type_Info_Tuple,
  120. Type_Info_Struct,
  121. Type_Info_Union,
  122. Type_Info_Enum,
  123. Type_Info_Map,
  124. Type_Info_Bit_Field,
  125. Type_Info_Bit_Set,
  126. },
  127. }
  128. // NOTE(bill): This must match the compiler's
  129. Typeid_Kind :: enum u8 {
  130. Invalid,
  131. Integer,
  132. Rune,
  133. Float,
  134. Complex,
  135. String,
  136. Boolean,
  137. Any,
  138. Type_Id,
  139. Pointer,
  140. Procedure,
  141. Array,
  142. Dynamic_Array,
  143. Slice,
  144. Tuple,
  145. Struct,
  146. Union,
  147. Enum,
  148. Map,
  149. Bit_Field,
  150. Bit_Set,
  151. }
  152. Typeid_Bit_Field :: bit_field #align align_of(uintptr) {
  153. index: 8*size_of(align_of(uintptr)) - 8,
  154. kind: 5, // Typeid_Kind
  155. named: 1,
  156. special: 1, // signed, cstring, etc
  157. reserved: 1,
  158. }
  159. // NOTE(bill): only the ones that are needed (not all types)
  160. // This will be set by the compiler
  161. type_table: []Type_Info;
  162. args__: []cstring;
  163. // IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
  164. Source_Code_Location :: struct {
  165. file_path: string,
  166. line, column: int,
  167. procedure: string,
  168. }
  169. Context :: struct {
  170. allocator: mem.Allocator,
  171. thread_id: int,
  172. user_data: any,
  173. user_index: int,
  174. parent: ^Context,
  175. derived: any, // May be used for derived data types
  176. }
  177. INITIAL_MAP_CAP :: 16;
  178. Map_Key :: struct {
  179. hash: u64,
  180. str: string,
  181. }
  182. Map_Find_Result :: struct {
  183. hash_index: int,
  184. entry_prev: int,
  185. entry_index: int,
  186. }
  187. Map_Entry_Header :: struct {
  188. key: Map_Key,
  189. next: int,
  190. /*
  191. value: Value_Type,
  192. */
  193. }
  194. Map_Header :: struct {
  195. m: ^mem.Raw_Map,
  196. is_key_string: bool,
  197. entry_size: int,
  198. entry_align: int,
  199. value_offset: uintptr,
  200. value_size: int,
  201. }
  202. type_info_base :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
  203. if info == nil do return nil;
  204. base := info;
  205. loop: for {
  206. switch i in base.variant {
  207. case Type_Info_Named: base = i.base;
  208. case: break loop;
  209. }
  210. }
  211. return base;
  212. }
  213. type_info_base_without_enum :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
  214. if info == nil do return nil;
  215. base := info;
  216. loop: for {
  217. switch i in base.variant {
  218. case Type_Info_Named: base = i.base;
  219. case Type_Info_Enum: base = i.base;
  220. case: break loop;
  221. }
  222. }
  223. return base;
  224. }
  225. __typeid_of :: proc "contextless" (ti: ^Type_Info) -> typeid {
  226. if ti == nil do return nil;
  227. return ti.id;
  228. }
  229. __type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info {
  230. data := transmute(Typeid_Bit_Field)id;
  231. n := int(data.index);
  232. if n < 0 || n >= len(type_table) {
  233. n = 0;
  234. }
  235. return &type_table[n];
  236. }
  237. typeid_base :: proc "contextless" (id: typeid) -> typeid {
  238. ti := type_info_of(id);
  239. ti = type_info_base(ti);
  240. return typeid_of(ti);
  241. }
  242. typeid_base_without_enum :: proc "contextless" (id: typeid) -> typeid {
  243. ti := type_info_base_without_enum(type_info_of(id));
  244. return typeid_of(ti);
  245. }
  246. @(default_calling_convention = "c")
  247. foreign {
  248. @(link_name="llvm.assume")
  249. assume :: proc(cond: bool) ---;
  250. @(link_name="llvm.debugtrap")
  251. debug_trap :: proc() ---;
  252. @(link_name="llvm.trap")
  253. trap :: proc() ---;
  254. @(link_name="llvm.readcyclecounter")
  255. read_cycle_counter :: proc() -> u64 ---;
  256. }
  257. __init_context_from_ptr :: proc "contextless" (c: ^Context, other: ^Context) {
  258. if c == nil do return;
  259. c^ = other^;
  260. __init_context(c);
  261. }
  262. __init_context :: proc "contextless" (c: ^Context) {
  263. if c == nil do return;
  264. c.allocator = os.heap_allocator();
  265. c.thread_id = os.current_thread_id();
  266. }
  267. @(builtin)
  268. copy :: proc "contextless" (dst, src: $T/[]$E) -> int {
  269. n := max(0, min(len(dst), len(src)));
  270. if n > 0 do mem.copy(&dst[0], &src[0], n*size_of(E));
  271. return n;
  272. }
  273. @(builtin)
  274. pop :: proc "contextless" (array: ^$T/[dynamic]$E) -> E {
  275. if array == nil do return E{};
  276. assert(len(array) > 0);
  277. res := array[len(array)-1];
  278. (^mem.Raw_Dynamic_Array)(array).len -= 1;
  279. return res;
  280. }
  281. @(builtin)
  282. clear :: proc[clear_dynamic_array, clear_map];
  283. @(builtin)
  284. reserve :: proc[reserve_dynamic_array, reserve_map];
  285. @(builtin)
  286. new :: proc[mem.new];
  287. @(builtin)
  288. new_clone :: proc[mem.new_clone];
  289. @(builtin)
  290. free :: proc[mem.free];
  291. @(builtin)
  292. delete :: proc[
  293. mem.delete_string,
  294. mem.delete_cstring,
  295. mem.delete_dynamic_array,
  296. mem.delete_slice,
  297. mem.delete_map,
  298. ];
  299. @(builtin)
  300. make :: proc[
  301. mem.make_slice,
  302. mem.make_dynamic_array,
  303. mem.make_dynamic_array_len,
  304. mem.make_dynamic_array_len_cap,
  305. mem.make_map,
  306. ];
  307. @(builtin)
  308. clear_map :: inline proc "contextless" (m: ^$T/map[$K]$V) {
  309. if m == nil do return;
  310. raw_map := (^mem.Raw_Map)(m);
  311. hashes := (^mem.Raw_Dynamic_Array)(&raw_map.hashes);
  312. entries := (^mem.Raw_Dynamic_Array)(&raw_map.entries);
  313. hashes.len = 0;
  314. entries.len = 0;
  315. }
  316. @(builtin)
  317. reserve_map :: proc(m: ^$T/map[$K]$V, capacity: int) {
  318. if m != nil do __dynamic_map_reserve(__get_map_header(m), capacity);
  319. }
  320. @(builtin)
  321. delete_key :: proc(m: ^$T/map[$K]$V, key: K) {
  322. if m != nil do __dynamic_map_delete_key(__get_map_header(m), __get_map_key(key));
  323. }
  324. @(builtin)
  325. append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) -> int {
  326. if array == nil do return 0;
  327. arg_len := 1;
  328. if cap(array) <= len(array)+arg_len {
  329. cap := 2 * cap(array) + max(8, arg_len);
  330. _ = reserve(array, cap, loc);
  331. }
  332. arg_len = min(cap(array)-len(array), arg_len);
  333. if arg_len > 0 {
  334. a := (^mem.Raw_Dynamic_Array)(array);
  335. data := (^E)(a.data);
  336. assert(data != nil);
  337. mem.copy(mem.ptr_offset(data, a.len), &arg, size_of(E));
  338. a.len += arg_len;
  339. }
  340. return len(array);
  341. }
  342. @(builtin)
  343. append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) -> int {
  344. if array == nil do return 0;
  345. arg_len := len(args);
  346. if arg_len <= 0 do return len(array);
  347. if cap(array) <= len(array)+arg_len {
  348. cap := 2 * cap(array) + max(8, arg_len);
  349. _ = reserve(array, cap, loc);
  350. }
  351. arg_len = min(cap(array)-len(array), arg_len);
  352. if arg_len > 0 {
  353. a := (^mem.Raw_Dynamic_Array)(array);
  354. data := (^E)(a.data);
  355. assert(data != nil);
  356. mem.copy(mem.ptr_offset(data, a.len), &args[0], size_of(E) * arg_len);
  357. a.len += arg_len;
  358. }
  359. return len(array);
  360. }
  361. @(builtin) append :: proc[append_elem, append_elems];
  362. @(builtin)
  363. append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) -> int {
  364. for arg in args {
  365. append(array = array, args = ([]E)(arg), loc = loc);
  366. }
  367. return len(array);
  368. }
  369. @(builtin)
  370. clear_dynamic_array :: inline proc "contextless" (array: ^$T/[dynamic]$E) {
  371. if array != nil do (^mem.Raw_Dynamic_Array)(array).len = 0;
  372. }
  373. @(builtin)
  374. reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> bool {
  375. if array == nil do return false;
  376. a := (^mem.Raw_Dynamic_Array)(array);
  377. if capacity <= a.cap do return true;
  378. if a.allocator.procedure == nil {
  379. a.allocator = context.allocator;
  380. }
  381. assert(a.allocator.procedure != nil);
  382. old_size := a.cap * size_of(E);
  383. new_size := capacity * size_of(E);
  384. allocator := a.allocator;
  385. new_data := allocator.procedure(
  386. allocator.data, mem.Allocator_Mode.Resize, new_size, align_of(E),
  387. a.data, old_size, 0, loc,
  388. );
  389. if new_data == nil do return false;
  390. a.data = new_data;
  391. a.cap = capacity;
  392. return true;
  393. }
  394. @(builtin)
  395. incl_elem :: inline proc(s: ^$S/bit_set[$E; $U], elem: E) -> S {
  396. s^ |= {elem};
  397. return s^;
  398. }
  399. @(builtin)
  400. incl_elems :: inline proc(s: ^$S/bit_set[$E; $U], elems: ..E) -> S {
  401. for elem in elems do s^ |= {elem};
  402. return s^;
  403. }
  404. @(builtin)
  405. incl_bit_set :: inline proc(s: ^$S/bit_set[$E; $U], other: S) -> S {
  406. s^ |= other;
  407. return s^;
  408. }
  409. @(builtin)
  410. excl_elem :: inline proc(s: ^$S/bit_set[$E; $U], elem: E) -> S {
  411. s^ &~= {elem};
  412. return s^;
  413. }
  414. @(builtin)
  415. excl_elems :: inline proc(s: ^$S/bit_set[$E; $U], elems: ..E) -> S {
  416. for elem in elems do s^ &~= {elem};
  417. return s^;
  418. }
  419. @(builtin)
  420. excl_bit_set :: inline proc(s: ^$S/bit_set[$E; $U], other: S) -> S {
  421. s^ &~= other;
  422. return s^;
  423. }
  424. @(builtin) incl :: proc[incl_elem, incl_elems, incl_bit_set];
  425. @(builtin) excl :: proc[excl_elem, excl_elems, excl_bit_set];
  426. @(builtin)
  427. assert :: proc "contextless" (condition: bool, message := "", using loc := #caller_location) -> bool {
  428. if !condition {
  429. fd := os.stderr;
  430. __print_caller_location(fd, loc);
  431. os.write_string(fd, " Runtime assertion");
  432. if len(message) > 0 {
  433. os.write_string(fd, ": ");
  434. os.write_string(fd, message);
  435. }
  436. os.write_byte(fd, '\n');
  437. debug_trap();
  438. }
  439. return condition;
  440. }
  441. @(builtin)
  442. panic :: proc "contextless" (message := "", using loc := #caller_location) {
  443. fd := os.stderr;
  444. __print_caller_location(fd, loc);
  445. os.write_string(fd, " Panic");
  446. if len(message) > 0 {
  447. os.write_string(fd, ": ");
  448. os.write_string(fd, message);
  449. }
  450. os.write_byte(fd, '\n');
  451. debug_trap();
  452. }
  453. // Dynamic Array
  454. __dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, cap: int, loc := #caller_location) {
  455. array := (^mem.Raw_Dynamic_Array)(array_);
  456. array.allocator = context.allocator;
  457. assert(array.allocator.procedure != nil);
  458. if cap > 0 {
  459. __dynamic_array_reserve(array_, elem_size, elem_align, cap, loc);
  460. array.len = len;
  461. }
  462. }
  463. __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap: int, loc := #caller_location) -> bool {
  464. array := (^mem.Raw_Dynamic_Array)(array_);
  465. if cap <= array.cap do return true;
  466. if array.allocator.procedure == nil {
  467. array.allocator = context.allocator;
  468. }
  469. assert(array.allocator.procedure != nil);
  470. old_size := array.cap * elem_size;
  471. new_size := cap * elem_size;
  472. allocator := array.allocator;
  473. new_data := allocator.procedure(allocator.data, mem.Allocator_Mode.Resize, new_size, elem_align, array.data, old_size, 0, loc);
  474. if new_data == nil do return false;
  475. array.data = new_data;
  476. array.cap = cap;
  477. return true;
  478. }
  479. __dynamic_array_resize :: proc(array_: rawptr, elem_size, elem_align: int, len: int, loc := #caller_location) -> bool {
  480. array := (^mem.Raw_Dynamic_Array)(array_);
  481. ok := __dynamic_array_reserve(array_, elem_size, elem_align, len, loc);
  482. if ok do array.len = len;
  483. return ok;
  484. }
  485. __dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int,
  486. items: rawptr, item_count: int, loc := #caller_location) -> int {
  487. array := (^mem.Raw_Dynamic_Array)(array_);
  488. if items == nil do return 0;
  489. if item_count <= 0 do return 0;
  490. ok := true;
  491. if array.cap <= array.len+item_count {
  492. cap := 2 * array.cap + max(8, item_count);
  493. ok = __dynamic_array_reserve(array, elem_size, elem_align, cap, loc);
  494. }
  495. // TODO(bill): Better error handling for failed reservation
  496. if !ok do return array.len;
  497. assert(array.data != nil);
  498. data := uintptr(array.data) + uintptr(elem_size*array.len);
  499. mem.copy(rawptr(data), items, elem_size * item_count);
  500. array.len += item_count;
  501. return array.len;
  502. }
  503. __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: int, loc := #caller_location) -> int {
  504. array := (^mem.Raw_Dynamic_Array)(array_);
  505. ok := true;
  506. if array.cap <= array.len+1 {
  507. cap := 2 * array.cap + max(8, 1);
  508. ok = __dynamic_array_reserve(array, elem_size, elem_align, cap, loc);
  509. }
  510. // TODO(bill): Better error handling for failed reservation
  511. if !ok do return array.len;
  512. assert(array.data != nil);
  513. data := uintptr(array.data) + uintptr(elem_size*array.len);
  514. mem.zero(rawptr(data), elem_size);
  515. array.len += 1;
  516. return array.len;
  517. }
  518. // Map
  519. __get_map_header :: proc "contextless" (m: ^$T/map[$K]$V) -> Map_Header {
  520. header := Map_Header{m = (^mem.Raw_Map)(m)};
  521. Entry :: struct {
  522. key: Map_Key,
  523. next: int,
  524. value: V,
  525. }
  526. _, is_string := type_info_base(type_info_of(K)).variant.(Type_Info_String);
  527. header.is_key_string = is_string;
  528. header.entry_size = int(size_of(Entry));
  529. header.entry_align = int(align_of(Entry));
  530. header.value_offset = uintptr(offset_of(Entry, value));
  531. header.value_size = int(size_of(V));
  532. return header;
  533. }
  534. __get_map_key :: proc "contextless" (key: $K) -> Map_Key {
  535. map_key: Map_Key;
  536. ti := type_info_base_without_enum(type_info_of(K));
  537. switch _ in ti.variant {
  538. case Type_Info_Integer:
  539. switch 8*size_of(key) {
  540. case 8: map_key.hash = u64(( ^u8)(&key)^);
  541. case 16: map_key.hash = u64(( ^u16)(&key)^);
  542. case 32: map_key.hash = u64(( ^u32)(&key)^);
  543. case 64: map_key.hash = u64(( ^u64)(&key)^);
  544. case: panic("Unhandled integer size");
  545. }
  546. case Type_Info_Rune:
  547. map_key.hash = u64((^rune)(&key)^);
  548. case Type_Info_Pointer:
  549. map_key.hash = u64(uintptr((^rawptr)(&key)^));
  550. case Type_Info_Float:
  551. switch 8*size_of(key) {
  552. case 32: map_key.hash = u64((^u32)(&key)^);
  553. case 64: map_key.hash = u64((^u64)(&key)^);
  554. case: panic("Unhandled float size");
  555. }
  556. case Type_Info_String:
  557. str := (^string)(&key)^;
  558. map_key.hash = __default_hash_string(str);
  559. map_key.str = str;
  560. case:
  561. panic("Unhandled map key type");
  562. }
  563. return map_key;
  564. }
  565. __default_hash :: proc(data: []byte) -> u64 {
  566. fnv64a :: proc(data: []byte) -> u64 {
  567. h: u64 = 0xcbf29ce484222325;
  568. for b in data {
  569. h = (h ~ u64(b)) * 0x100000001b3;
  570. }
  571. return h;
  572. }
  573. return fnv64a(data);
  574. }
  575. __default_hash_string :: proc(s: string) -> u64 do return __default_hash(([]byte)(s));
  576. __dynamic_map_reserve :: proc(using header: Map_Header, cap: int, loc := #caller_location) {
  577. __dynamic_array_reserve(&m.hashes, size_of(int), align_of(int), cap, loc);
  578. __dynamic_array_reserve(&m.entries, entry_size, entry_align, cap, loc);
  579. }
  580. __dynamic_map_rehash :: proc(using header: Map_Header, new_count: int, loc := #caller_location) #no_bounds_check {
  581. new_header: Map_Header = header;
  582. nm := mem.Raw_Map{};
  583. new_header.m = &nm;
  584. header_hashes := (^mem.Raw_Dynamic_Array)(&header.m.hashes);
  585. nm_hashes := (^mem.Raw_Dynamic_Array)(&nm.hashes);
  586. __dynamic_array_resize(nm_hashes, size_of(int), align_of(int), new_count, loc);
  587. __dynamic_array_reserve(&nm.entries, entry_size, entry_align, m.entries.len, loc);
  588. for i in 0 .. new_count-1 do nm.hashes[i] = -1;
  589. for i in 0 .. m.entries.len-1 {
  590. if len(nm.hashes) == 0 do __dynamic_map_grow(new_header, loc);
  591. entry_header := __dynamic_map_get_entry(header, i);
  592. data := uintptr(entry_header);
  593. fr := __dynamic_map_find(new_header, entry_header.key);
  594. j := __dynamic_map_add_entry(new_header, entry_header.key, loc);
  595. if fr.entry_prev < 0 {
  596. nm.hashes[fr.hash_index] = j;
  597. } else {
  598. e := __dynamic_map_get_entry(new_header, fr.entry_prev);
  599. e.next = j;
  600. }
  601. e := __dynamic_map_get_entry(new_header, j);
  602. e.next = fr.entry_index;
  603. ndata := uintptr(e);
  604. mem.copy(rawptr(ndata+value_offset), rawptr(data+value_offset), value_size);
  605. if __dynamic_map_full(new_header) do __dynamic_map_grow(new_header, loc);
  606. }
  607. mem.free_ptr_with_allocator(header_hashes.allocator, header_hashes.data, loc);
  608. mem.free_ptr_with_allocator(header.m.entries.allocator, header.m.entries.data, loc);
  609. header.m^ = nm;
  610. }
  611. __dynamic_map_get :: proc(h: Map_Header, key: Map_Key) -> rawptr {
  612. index := __dynamic_map_find(h, key).entry_index;
  613. if index >= 0 {
  614. data := uintptr(__dynamic_map_get_entry(h, index));
  615. return rawptr(data + h.value_offset);
  616. }
  617. return nil;
  618. }
  619. __dynamic_map_set :: proc(h: Map_Header, key: Map_Key, value: rawptr, loc := #caller_location) #no_bounds_check {
  620. index: int;
  621. assert(value != nil);
  622. if len(h.m.hashes) == 0 {
  623. __dynamic_map_reserve(h, INITIAL_MAP_CAP, loc);
  624. __dynamic_map_grow(h, loc);
  625. }
  626. fr := __dynamic_map_find(h, key);
  627. if fr.entry_index >= 0 {
  628. index = fr.entry_index;
  629. } else {
  630. index = __dynamic_map_add_entry(h, key, loc);
  631. if fr.entry_prev >= 0 {
  632. entry := __dynamic_map_get_entry(h, fr.entry_prev);
  633. entry.next = index;
  634. } else {
  635. h.m.hashes[fr.hash_index] = index;
  636. }
  637. }
  638. {
  639. e := __dynamic_map_get_entry(h, index);
  640. e.key = key;
  641. val := (^byte)(uintptr(e) + h.value_offset);
  642. mem.copy(val, value, h.value_size);
  643. }
  644. if __dynamic_map_full(h) {
  645. __dynamic_map_grow(h, loc);
  646. }
  647. }
  648. __dynamic_map_grow :: proc(using h: Map_Header, loc := #caller_location) {
  649. // TODO(bill): Determine an efficient growing rate
  650. new_count := max(4*m.entries.cap + 7, INITIAL_MAP_CAP);
  651. __dynamic_map_rehash(h, new_count, loc);
  652. }
  653. __dynamic_map_full :: inline proc(using h: Map_Header) -> bool {
  654. return int(0.75 * f64(len(m.hashes))) <= m.entries.cap;
  655. }
  656. __dynamic_map_hash_equal :: proc(h: Map_Header, a, b: Map_Key) -> bool {
  657. if a.hash == b.hash {
  658. if h.is_key_string do return a.str == b.str;
  659. return true;
  660. }
  661. return false;
  662. }
  663. __dynamic_map_find :: proc(using h: Map_Header, key: Map_Key) -> Map_Find_Result #no_bounds_check {
  664. fr := Map_Find_Result{-1, -1, -1};
  665. if n := u64(len(m.hashes)); n > 0 {
  666. fr.hash_index = int(key.hash % n);
  667. fr.entry_index = m.hashes[fr.hash_index];
  668. for fr.entry_index >= 0 {
  669. entry := __dynamic_map_get_entry(h, fr.entry_index);
  670. if __dynamic_map_hash_equal(h, entry.key, key) do return fr;
  671. fr.entry_prev = fr.entry_index;
  672. fr.entry_index = entry.next;
  673. }
  674. }
  675. return fr;
  676. }
  677. __dynamic_map_add_entry :: proc(using h: Map_Header, key: Map_Key, loc := #caller_location) -> int {
  678. prev := m.entries.len;
  679. c := __dynamic_array_append_nothing(&m.entries, entry_size, entry_align, loc);
  680. if c != prev {
  681. end := __dynamic_map_get_entry(h, c-1);
  682. end.key = key;
  683. end.next = -1;
  684. }
  685. return prev;
  686. }
  687. __dynamic_map_delete_key :: proc(using h: Map_Header, key: Map_Key) {
  688. fr := __dynamic_map_find(h, key);
  689. if fr.entry_index >= 0 {
  690. __dynamic_map_erase(h, fr);
  691. }
  692. }
  693. __dynamic_map_get_entry :: proc(using h: Map_Header, index: int) -> ^Map_Entry_Header {
  694. assert(0 <= index && index < m.entries.len);
  695. return (^Map_Entry_Header)(uintptr(m.entries.data) + uintptr(index*entry_size));
  696. }
  697. __dynamic_map_erase :: proc(using h: Map_Header, fr: Map_Find_Result) #no_bounds_check {
  698. if fr.entry_prev < 0 {
  699. m.hashes[fr.hash_index] = __dynamic_map_get_entry(h, fr.entry_index).next;
  700. } else {
  701. prev := __dynamic_map_get_entry(h, fr.entry_prev);
  702. curr := __dynamic_map_get_entry(h, fr.entry_index);
  703. prev.next = curr.next;
  704. }
  705. if (fr.entry_index == m.entries.len-1) {
  706. m.entries.len -= 1;
  707. return;
  708. }
  709. last := __dynamic_map_find(h, __dynamic_map_get_entry(h, fr.entry_index).key);
  710. if last.entry_prev >= 0 {
  711. last_entry := __dynamic_map_get_entry(h, last.entry_prev);
  712. last_entry.next = fr.entry_index;
  713. } else {
  714. m.hashes[last.hash_index] = fr.entry_index;
  715. }
  716. }