core.odin 25 KB

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