core.odin 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470
  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 "intrinsics"
  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. Platform_Endianness :: enum u8 {
  36. Platform = 0,
  37. Little = 1,
  38. Big = 2,
  39. }
  40. Type_Info_Struct_Soa_Kind :: enum u8 {
  41. None = 0,
  42. Fixed = 1,
  43. Slice = 2,
  44. Dynamic = 3,
  45. }
  46. // Variant Types
  47. Type_Info_Named :: struct {name: string, base: ^Type_Info};
  48. Type_Info_Integer :: struct {signed: bool, endianness: Platform_Endianness};
  49. Type_Info_Rune :: struct {};
  50. Type_Info_Float :: struct {};
  51. Type_Info_Complex :: struct {};
  52. Type_Info_Quaternion :: struct {};
  53. Type_Info_String :: struct {is_cstring: bool};
  54. Type_Info_Boolean :: struct {};
  55. Type_Info_Any :: struct {};
  56. Type_Info_Type_Id :: struct {};
  57. Type_Info_Pointer :: struct {
  58. elem: ^Type_Info // nil -> rawptr
  59. };
  60. Type_Info_Procedure :: struct {
  61. params: ^Type_Info, // Type_Info_Tuple
  62. results: ^Type_Info, // Type_Info_Tuple
  63. variadic: bool,
  64. convention: Calling_Convention,
  65. };
  66. Type_Info_Array :: struct {
  67. elem: ^Type_Info,
  68. elem_size: int,
  69. count: int,
  70. };
  71. Type_Info_Enumerated_Array :: struct {
  72. elem: ^Type_Info,
  73. index: ^Type_Info,
  74. elem_size: int,
  75. count: int,
  76. min_value: Type_Info_Enum_Value,
  77. max_value: Type_Info_Enum_Value,
  78. };
  79. Type_Info_Dynamic_Array :: struct {elem: ^Type_Info, elem_size: int};
  80. Type_Info_Slice :: struct {elem: ^Type_Info, elem_size: int};
  81. Type_Info_Tuple :: struct { // Only really used for procedures
  82. types: []^Type_Info,
  83. names: []string,
  84. };
  85. Type_Info_Struct :: struct {
  86. types: []^Type_Info,
  87. names: []string,
  88. offsets: []uintptr,
  89. usings: []bool,
  90. tags: []string,
  91. is_packed: bool,
  92. is_raw_union: bool,
  93. custom_align: bool,
  94. // These are only set iff this structure is an SOA structure
  95. soa_kind: Type_Info_Struct_Soa_Kind,
  96. soa_base_type: ^Type_Info,
  97. soa_len: int,
  98. };
  99. Type_Info_Union :: struct {
  100. variants: []^Type_Info,
  101. tag_offset: uintptr,
  102. tag_type: ^Type_Info,
  103. custom_align: bool,
  104. no_nil: bool,
  105. };
  106. Type_Info_Enum :: struct {
  107. base: ^Type_Info,
  108. names: []string,
  109. values: []Type_Info_Enum_Value,
  110. };
  111. Type_Info_Map :: struct {
  112. key: ^Type_Info,
  113. value: ^Type_Info,
  114. generated_struct: ^Type_Info,
  115. };
  116. Type_Info_Bit_Field :: struct {
  117. names: []string,
  118. bits: []i32,
  119. offsets: []i32,
  120. };
  121. Type_Info_Bit_Set :: struct {
  122. elem: ^Type_Info,
  123. underlying: ^Type_Info, // Possibly nil
  124. lower: i64,
  125. upper: i64,
  126. };
  127. Type_Info_Opaque :: struct {
  128. elem: ^Type_Info,
  129. };
  130. Type_Info_Simd_Vector :: struct {
  131. elem: ^Type_Info,
  132. elem_size: int,
  133. count: int,
  134. is_x86_mmx: bool,
  135. }
  136. Type_Info :: struct {
  137. size: int,
  138. align: int,
  139. id: typeid,
  140. variant: union {
  141. Type_Info_Named,
  142. Type_Info_Integer,
  143. Type_Info_Rune,
  144. Type_Info_Float,
  145. Type_Info_Complex,
  146. Type_Info_Quaternion,
  147. Type_Info_String,
  148. Type_Info_Boolean,
  149. Type_Info_Any,
  150. Type_Info_Type_Id,
  151. Type_Info_Pointer,
  152. Type_Info_Procedure,
  153. Type_Info_Array,
  154. Type_Info_Enumerated_Array,
  155. Type_Info_Dynamic_Array,
  156. Type_Info_Slice,
  157. Type_Info_Tuple,
  158. Type_Info_Struct,
  159. Type_Info_Union,
  160. Type_Info_Enum,
  161. Type_Info_Map,
  162. Type_Info_Bit_Field,
  163. Type_Info_Bit_Set,
  164. Type_Info_Opaque,
  165. Type_Info_Simd_Vector,
  166. },
  167. }
  168. // NOTE(bill): This must match the compiler's
  169. Typeid_Kind :: enum u8 {
  170. Invalid,
  171. Integer,
  172. Rune,
  173. Float,
  174. Complex,
  175. Quaternion,
  176. String,
  177. Boolean,
  178. Any,
  179. Type_Id,
  180. Pointer,
  181. Procedure,
  182. Array,
  183. Enumerated_Array,
  184. Dynamic_Array,
  185. Slice,
  186. Tuple,
  187. Struct,
  188. Union,
  189. Enum,
  190. Map,
  191. Bit_Field,
  192. Bit_Set,
  193. Opaque,
  194. }
  195. #assert(len(Typeid_Kind) < 32);
  196. Typeid_Bit_Field :: bit_field #align align_of(uintptr) {
  197. index: 8*size_of(uintptr) - 8,
  198. kind: 5, // Typeid_Kind
  199. named: 1,
  200. special: 1, // signed, cstring, etc
  201. reserved: 1,
  202. }
  203. #assert(size_of(Typeid_Bit_Field) == size_of(uintptr));
  204. // NOTE(bill): only the ones that are needed (not all types)
  205. // This will be set by the compiler
  206. type_table: []Type_Info;
  207. args__: []cstring;
  208. // IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
  209. Source_Code_Location :: struct {
  210. file_path: string,
  211. line, column: int,
  212. procedure: string,
  213. hash: u64,
  214. }
  215. Assertion_Failure_Proc :: #type proc(prefix, message: string, loc: Source_Code_Location);
  216. // Allocation Stuff
  217. Allocator_Mode :: enum byte {
  218. Alloc,
  219. Free,
  220. Free_All,
  221. Resize,
  222. }
  223. Allocator_Proc :: #type proc(allocator_data: rawptr, mode: Allocator_Mode,
  224. size, alignment: int,
  225. old_memory: rawptr, old_size: int, flags: u64 = 0, location: Source_Code_Location = #caller_location) -> rawptr;
  226. Allocator :: struct {
  227. procedure: Allocator_Proc,
  228. data: rawptr,
  229. }
  230. // Logging stuff
  231. Logger_Level :: enum {
  232. Debug,
  233. Info,
  234. Warning,
  235. Error,
  236. Fatal,
  237. }
  238. Logger_Option :: enum {
  239. Level,
  240. Date,
  241. Time,
  242. Short_File_Path,
  243. Long_File_Path,
  244. Line,
  245. Procedure,
  246. Terminal_Color
  247. }
  248. Logger_Options :: bit_set[Logger_Option];
  249. Logger_Proc :: #type proc(data: rawptr, level: Logger_Level, text: string, options: Logger_Options, location := #caller_location);
  250. Logger :: struct {
  251. procedure: Logger_Proc,
  252. data: rawptr,
  253. options: Logger_Options,
  254. }
  255. Context :: struct {
  256. allocator: Allocator,
  257. temp_allocator: Allocator,
  258. assertion_failure_proc: Assertion_Failure_Proc,
  259. logger: Logger,
  260. stdin: os.Handle,
  261. stdout: os.Handle,
  262. stderr: os.Handle,
  263. thread_id: int,
  264. user_data: any,
  265. user_ptr: rawptr,
  266. user_index: int,
  267. }
  268. @thread_local global_default_temp_allocator_data: Default_Temp_Allocator;
  269. Raw_String :: struct {
  270. data: ^byte,
  271. len: int,
  272. }
  273. Raw_Slice :: struct {
  274. data: rawptr,
  275. len: int,
  276. }
  277. Raw_Dynamic_Array :: struct {
  278. data: rawptr,
  279. len: int,
  280. cap: int,
  281. allocator: Allocator,
  282. }
  283. Raw_Map :: struct {
  284. hashes: []int,
  285. entries: Raw_Dynamic_Array,
  286. }
  287. INITIAL_MAP_CAP :: 16;
  288. Map_Key :: struct {
  289. hash: u64,
  290. str: string,
  291. }
  292. Map_Find_Result :: struct {
  293. hash_index: int,
  294. entry_prev: int,
  295. entry_index: int,
  296. }
  297. Map_Entry_Header :: struct {
  298. key: Map_Key,
  299. next: int,
  300. /*
  301. value: Value_Type,
  302. */
  303. }
  304. Map_Header :: struct {
  305. m: ^Raw_Map,
  306. is_key_string: bool,
  307. entry_size: int,
  308. entry_align: int,
  309. value_offset: uintptr,
  310. value_size: int,
  311. }
  312. type_info_base :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
  313. if info == nil do return nil;
  314. base := info;
  315. loop: for {
  316. #partial switch i in base.variant {
  317. case Type_Info_Named: base = i.base;
  318. case: break loop;
  319. }
  320. }
  321. return base;
  322. }
  323. type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
  324. if info == nil do return nil;
  325. base := info;
  326. loop: for {
  327. #partial switch i in base.variant {
  328. case Type_Info_Named: base = i.base;
  329. case Type_Info_Enum: base = i.base;
  330. case Type_Info_Opaque: base = i.elem;
  331. case: break loop;
  332. }
  333. }
  334. return base;
  335. }
  336. type_info_base_without_enum :: type_info_core;
  337. __type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info {
  338. data := transmute(Typeid_Bit_Field)id;
  339. n := int(data.index);
  340. if n < 0 || n >= len(type_table) {
  341. n = 0;
  342. }
  343. return &type_table[n];
  344. }
  345. typeid_base :: proc "contextless" (id: typeid) -> typeid {
  346. ti := type_info_of(id);
  347. ti = type_info_base(ti);
  348. return ti.id;
  349. }
  350. typeid_core :: proc "contextless" (id: typeid) -> typeid {
  351. ti := type_info_base_without_enum(type_info_of(id));
  352. return ti.id;
  353. }
  354. typeid_base_without_enum :: typeid_core;
  355. @(default_calling_convention = "c")
  356. foreign {
  357. @(link_name="llvm.assume")
  358. assume :: proc(cond: bool) ---;
  359. @(link_name="llvm.debugtrap")
  360. debug_trap :: proc() ---;
  361. @(link_name="llvm.trap")
  362. trap :: proc() -> ! ---;
  363. @(link_name="llvm.readcyclecounter")
  364. read_cycle_counter :: proc() -> u64 ---;
  365. }
  366. default_logger_proc :: proc(data: rawptr, level: Logger_Level, text: string, options: Logger_Options, location := #caller_location) {
  367. // Do nothing
  368. }
  369. default_logger :: proc() -> Logger {
  370. return Logger{default_logger_proc, nil, nil};
  371. }
  372. @private
  373. __init_context_from_ptr :: proc "contextless" (c: ^Context, other: ^Context) {
  374. if c == nil do return;
  375. c^ = other^;
  376. __init_context(c);
  377. }
  378. @private
  379. __init_context :: proc "contextless" (c: ^Context) {
  380. if c == nil do return;
  381. // NOTE(bill): Do not initialize these procedures with a call as they are not defined with the "contexless" calling convention
  382. c.allocator.procedure = default_allocator_proc;
  383. c.allocator.data = nil;
  384. c.temp_allocator.procedure = default_temp_allocator_proc;
  385. c.temp_allocator.data = &global_default_temp_allocator_data;
  386. c.thread_id = os.current_thread_id(); // NOTE(bill): This is "contextless" so it is okay to call
  387. c.assertion_failure_proc = default_assertion_failure_proc;
  388. c.logger.procedure = default_logger_proc;
  389. c.logger.data = nil;
  390. c.stdin = os.stdin;
  391. c.stdout = os.stdout;
  392. c.stderr = os.stderr;
  393. }
  394. @builtin
  395. init_global_temporary_allocator :: proc(data: []byte, backup_allocator := context.allocator) {
  396. default_temp_allocator_init(&global_default_temp_allocator_data, data, backup_allocator);
  397. }
  398. default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) {
  399. fd := context.stderr;
  400. print_caller_location(fd, loc);
  401. os.write_string(fd, " ");
  402. os.write_string(fd, prefix);
  403. if len(message) > 0 {
  404. os.write_string(fd, ": ");
  405. os.write_string(fd, message);
  406. }
  407. os.write_byte(fd, '\n');
  408. debug_trap();
  409. }
  410. @builtin
  411. copy_slice :: proc "contextless" (dst, src: $T/[]$E) -> int {
  412. n := max(0, min(len(dst), len(src)));
  413. #no_bounds_check if n > 0 do mem_copy(&dst[0], &src[0], n*size_of(E));
  414. return n;
  415. }
  416. @builtin
  417. copy_from_string :: proc "contextless" (dst: $T/[]$E/u8, src: $S/string) -> int {
  418. n := max(0, min(len(dst), len(src)));
  419. if n > 0 {
  420. d := (transmute(Raw_Slice)dst).data;
  421. s := (transmute(Raw_String)src).data;
  422. mem_copy(d, s, n);
  423. }
  424. return n;
  425. }
  426. @builtin
  427. copy :: proc{copy_slice, copy_from_string};
  428. @builtin
  429. pop :: proc "contextless" (array: ^$T/[dynamic]$E) -> E {
  430. if array == nil do return E{};
  431. assert(len(array) > 0);
  432. res := #no_bounds_check array[len(array)-1];
  433. (^Raw_Dynamic_Array)(array).len -= 1;
  434. return res;
  435. }
  436. @builtin
  437. unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) {
  438. bounds_check_error_loc(loc, index, len(array));
  439. n := len(array)-1;
  440. if index != n {
  441. array[index] = array[n];
  442. }
  443. pop(array);
  444. }
  445. @builtin
  446. ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) {
  447. bounds_check_error_loc(loc, index, len(array));
  448. if index+1 < len(array) {
  449. copy(array[index:], array[index+1:]);
  450. }
  451. pop(array);
  452. }
  453. @builtin
  454. clear :: proc{clear_dynamic_array, clear_map};
  455. @builtin
  456. reserve :: proc{reserve_dynamic_array, reserve_map};
  457. @builtin
  458. resize :: proc{resize_dynamic_array};
  459. @builtin
  460. free :: proc{mem_free};
  461. @builtin
  462. free_all :: proc{mem_free_all};
  463. @builtin
  464. delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) {
  465. mem_free((transmute(Raw_String)str).data, allocator, loc);
  466. }
  467. @builtin
  468. delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) {
  469. mem_free((^byte)(str), allocator, loc);
  470. }
  471. @builtin
  472. delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) {
  473. mem_free((transmute(Raw_Dynamic_Array)array).data, array.allocator, loc);
  474. }
  475. @builtin
  476. delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) {
  477. mem_free((transmute(Raw_Slice)array).data, allocator, loc);
  478. }
  479. @builtin
  480. delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) {
  481. raw := transmute(Raw_Map)m;
  482. delete_slice(raw.hashes);
  483. mem_free(raw.entries.data, raw.entries.allocator, loc);
  484. }
  485. @builtin
  486. delete :: proc{
  487. delete_string,
  488. delete_cstring,
  489. delete_dynamic_array,
  490. delete_slice,
  491. delete_map,
  492. };
  493. @builtin
  494. new :: inline proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> ^T {
  495. ptr := (^T)(mem_alloc(size_of(T), align_of(T), allocator, loc));
  496. if ptr != nil do ptr^ = T{};
  497. return ptr;
  498. }
  499. @builtin
  500. new_clone :: inline proc(data: $T, allocator := context.allocator, loc := #caller_location) -> ^T {
  501. ptr := (^T)(mem_alloc(size_of(T), align_of(T), allocator, loc));
  502. if ptr != nil do ptr^ = data;
  503. return ptr;
  504. }
  505. make_aligned :: proc($T: typeid/[]$E, auto_cast len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> T {
  506. make_slice_error_loc(loc, len);
  507. data := mem_alloc(size_of(E)*len, alignment, allocator, loc);
  508. if data == nil do return nil;
  509. s := Raw_Slice{data, len};
  510. return transmute(T)s;
  511. }
  512. @builtin
  513. make_slice :: inline proc($T: typeid/[]$E, auto_cast len: int, allocator := context.allocator, loc := #caller_location) -> T {
  514. return make_aligned(T, len, align_of(E), allocator, loc);
  515. }
  516. @builtin
  517. make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> T {
  518. return make_dynamic_array_len_cap(T, 0, 16, allocator, loc);
  519. }
  520. @builtin
  521. make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, auto_cast len: int, allocator := context.allocator, loc := #caller_location) -> T {
  522. return make_dynamic_array_len_cap(T, len, len, allocator, loc);
  523. }
  524. @builtin
  525. make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, auto_cast len: int, auto_cast cap: int, allocator := context.allocator, loc := #caller_location) -> T {
  526. make_dynamic_array_error_loc(loc, len, cap);
  527. data := mem_alloc(size_of(E)*cap, align_of(E), allocator, loc);
  528. s := Raw_Dynamic_Array{data, len, cap, allocator};
  529. if data == nil {
  530. s.len, s.cap = 0, 0;
  531. }
  532. return transmute(T)s;
  533. }
  534. @builtin
  535. make_map :: proc($T: typeid/map[$K]$E, auto_cast cap: int = 16, allocator := context.allocator, loc := #caller_location) -> T {
  536. make_map_expr_error_loc(loc, cap);
  537. context.allocator = allocator;
  538. m: T;
  539. reserve_map(&m, cap);
  540. return m;
  541. }
  542. @builtin
  543. make :: proc{
  544. make_slice,
  545. make_dynamic_array,
  546. make_dynamic_array_len,
  547. make_dynamic_array_len_cap,
  548. make_map,
  549. };
  550. @builtin
  551. clear_map :: inline proc "contextless" (m: ^$T/map[$K]$V) {
  552. if m == nil do return;
  553. raw_map := (^Raw_Map)(m);
  554. entries := (^Raw_Dynamic_Array)(&raw_map.entries);
  555. entries.len = 0;
  556. for _, i in raw_map.hashes {
  557. raw_map.hashes[i] = -1;
  558. }
  559. }
  560. @builtin
  561. reserve_map :: proc(m: ^$T/map[$K]$V, capacity: int) {
  562. if m != nil do __dynamic_map_reserve(__get_map_header(m), capacity);
  563. }
  564. @builtin
  565. delete_key :: proc(m: ^$T/map[$K]$V, key: K) {
  566. if m != nil do __dynamic_map_delete_key(__get_map_header(m), __get_map_key(key));
  567. }
  568. @builtin
  569. append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) {
  570. if array == nil do return;
  571. arg_len := 1;
  572. if cap(array) <= len(array)+arg_len {
  573. cap := 2 * cap(array) + max(8, arg_len);
  574. _ = reserve(array, cap, loc);
  575. }
  576. arg_len = min(cap(array)-len(array), arg_len);
  577. if arg_len > 0 {
  578. a := (^Raw_Dynamic_Array)(array);
  579. data := (^E)(a.data);
  580. assert(data != nil);
  581. val := arg;
  582. mem_copy(ptr_offset(data, a.len), &val, size_of(E));
  583. a.len += arg_len;
  584. }
  585. }
  586. @builtin
  587. append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) {
  588. if array == nil do return;
  589. arg_len := len(args);
  590. if arg_len <= 0 do return;
  591. if cap(array) <= len(array)+arg_len {
  592. cap := 2 * cap(array) + max(8, arg_len);
  593. _ = reserve(array, cap, loc);
  594. }
  595. arg_len = min(cap(array)-len(array), arg_len);
  596. if arg_len > 0 {
  597. a := (^Raw_Dynamic_Array)(array);
  598. data := (^E)(a.data);
  599. assert(data != nil);
  600. mem_copy(ptr_offset(data, a.len), &args[0], size_of(E) * arg_len);
  601. a.len += arg_len;
  602. }
  603. }
  604. @builtin
  605. append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) {
  606. args := transmute([]E)arg;
  607. append_elems(array=array, args=args, loc=loc);
  608. }
  609. @builtin
  610. reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_location) -> bool {
  611. if array == nil do return false;
  612. old_cap := cap(array);
  613. if capacity <= old_cap do return true;
  614. if array.allocator.procedure == nil {
  615. array.allocator = context.allocator;
  616. }
  617. assert(array.allocator.procedure != nil);
  618. ti := type_info_of(typeid_of(T));
  619. ti = type_info_base(ti);
  620. si := &ti.variant.(Type_Info_Struct);
  621. field_count := uintptr(len(si.offsets) - 3);
  622. if field_count == 0 {
  623. return true;
  624. }
  625. cap_ptr := cast(^int)rawptr(uintptr(array) + (field_count + 1)*size_of(rawptr));
  626. assert(cap_ptr^ == old_cap);
  627. old_size := 0;
  628. new_size := 0;
  629. max_align := 0;
  630. for i in 0..<field_count {
  631. type := si.types[i].variant.(Type_Info_Pointer).elem;
  632. max_align = max(max_align, type.align);
  633. old_size = align_forward_int(old_size, type.align);
  634. new_size = align_forward_int(new_size, type.align);
  635. old_size += type.size * old_cap;
  636. new_size += type.size * capacity;
  637. }
  638. old_size = align_forward_int(old_size, max_align);
  639. new_size = align_forward_int(new_size, max_align);
  640. old_data := (^rawptr)(array)^;
  641. new_data := array.allocator.procedure(
  642. array.allocator.data, .Alloc, new_size, max_align,
  643. nil, old_size, 0, loc,
  644. );
  645. if new_data == nil do return false;
  646. cap_ptr^ = capacity;
  647. old_offset := 0;
  648. new_offset := 0;
  649. for i in 0..<field_count {
  650. type := si.types[i].variant.(Type_Info_Pointer).elem;
  651. max_align = max(max_align, type.align);
  652. old_offset = align_forward_int(old_offset, type.align);
  653. new_offset = align_forward_int(new_offset, type.align);
  654. new_data_elem := rawptr(uintptr(new_data) + uintptr(new_offset));
  655. old_data_elem := rawptr(uintptr(old_data) + uintptr(old_offset));
  656. mem_copy(new_data_elem, old_data_elem, type.size * old_cap);
  657. (^rawptr)(uintptr(array) + i*size_of(rawptr))^ = new_data_elem;
  658. old_offset += type.size * old_cap;
  659. new_offset += type.size * capacity;
  660. }
  661. array.allocator.procedure(
  662. array.allocator.data, .Free, 0, max_align,
  663. old_data, old_size, 0, loc,
  664. );
  665. return true;
  666. }
  667. @builtin
  668. append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, arg: E, loc := #caller_location) {
  669. if array == nil do return;
  670. arg_len := 1;
  671. if cap(array) <= len(array)+arg_len {
  672. cap := 2 * cap(array) + max(8, arg_len);
  673. _ = reserve_soa(array, cap, loc);
  674. }
  675. arg_len = min(cap(array)-len(array), arg_len);
  676. if arg_len > 0 {
  677. ti := type_info_of(typeid_of(T));
  678. ti = type_info_base(ti);
  679. si := &ti.variant.(Type_Info_Struct);
  680. field_count := uintptr(len(si.offsets) - 3);
  681. if field_count == 0 {
  682. return;
  683. }
  684. data := (^rawptr)(array)^;
  685. len_ptr := cast(^int)rawptr(uintptr(array) + (field_count + 0)*size_of(rawptr));
  686. soa_offset := 0;
  687. item_offset := 0;
  688. arg_copy := arg;
  689. arg_ptr := &arg_copy;
  690. max_align := 0;
  691. for i in 0..<field_count {
  692. type := si.types[i].variant.(Type_Info_Pointer).elem;
  693. max_align = max(max_align, type.align);
  694. soa_offset = align_forward_int(soa_offset, type.align);
  695. item_offset = align_forward_int(item_offset, type.align);
  696. dst := rawptr(uintptr(data) + uintptr(soa_offset) + uintptr(type.size * len_ptr^));
  697. src := rawptr(uintptr(arg_ptr) + uintptr(item_offset));
  698. mem_copy(dst, src, type.size);
  699. soa_offset += type.size * cap(array);
  700. item_offset += type.size;
  701. }
  702. len_ptr^ += arg_len;
  703. }
  704. }
  705. @builtin
  706. append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_location) {
  707. if array == nil do return;
  708. arg_len := len(args);
  709. if arg_len == 0 {
  710. return;
  711. }
  712. if cap(array) <= len(array)+arg_len {
  713. cap := 2 * cap(array) + max(8, arg_len);
  714. _ = reserve_soa(array, cap, loc);
  715. }
  716. arg_len = min(cap(array)-len(array), arg_len);
  717. if arg_len > 0 {
  718. ti := type_info_of(typeid_of(T));
  719. ti = type_info_base(ti);
  720. si := &ti.variant.(Type_Info_Struct);
  721. field_count := uintptr(len(si.offsets) - 3);
  722. if field_count == 0 {
  723. return;
  724. }
  725. data := (^rawptr)(array)^;
  726. len_ptr := cast(^int)rawptr(uintptr(array) + (field_count + 0)*size_of(rawptr));
  727. soa_offset := 0;
  728. item_offset := 0;
  729. args_ptr := &args[0];
  730. max_align := 0;
  731. for i in 0..<field_count {
  732. type := si.types[i].variant.(Type_Info_Pointer).elem;
  733. max_align = max(max_align, type.align);
  734. soa_offset = align_forward_int(soa_offset, type.align);
  735. item_offset = align_forward_int(item_offset, type.align);
  736. dst := uintptr(data) + uintptr(soa_offset) + uintptr(type.size * len_ptr^);
  737. src := uintptr(args_ptr) + uintptr(item_offset);
  738. for j in 0..<arg_len {
  739. d := rawptr(dst + uintptr(j*type.size));
  740. s := rawptr(src + uintptr(j*size_of(E)));
  741. mem_copy(d, s, type.size);
  742. }
  743. soa_offset += type.size * cap(array);
  744. item_offset += type.size;
  745. }
  746. len_ptr^ += arg_len;
  747. }
  748. }
  749. @builtin append :: proc{append_elem, append_elems, append_elem_string};
  750. @builtin append_soa :: proc{append_soa_elem, append_soa_elems};
  751. @builtin
  752. append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) {
  753. for arg in args {
  754. append(array = array, args = transmute([]E)(arg), loc = loc);
  755. }
  756. }
  757. @builtin
  758. clear_dynamic_array :: inline proc "contextless" (array: ^$T/[dynamic]$E) {
  759. if array != nil do (^Raw_Dynamic_Array)(array).len = 0;
  760. }
  761. @builtin
  762. reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> bool {
  763. if array == nil do return false;
  764. a := (^Raw_Dynamic_Array)(array);
  765. if capacity <= a.cap do return true;
  766. if a.allocator.procedure == nil {
  767. a.allocator = context.allocator;
  768. }
  769. assert(a.allocator.procedure != nil);
  770. old_size := a.cap * size_of(E);
  771. new_size := capacity * size_of(E);
  772. allocator := a.allocator;
  773. new_data := allocator.procedure(
  774. allocator.data, .Resize, new_size, align_of(E),
  775. a.data, old_size, 0, loc,
  776. );
  777. if new_data == nil do return false;
  778. a.data = new_data;
  779. a.cap = capacity;
  780. return true;
  781. }
  782. @builtin
  783. resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> bool {
  784. if array == nil do return false;
  785. a := (^Raw_Dynamic_Array)(array);
  786. if length <= a.cap {
  787. a.len = max(length, 0);
  788. return true;
  789. }
  790. if a.allocator.procedure == nil {
  791. a.allocator = context.allocator;
  792. }
  793. assert(a.allocator.procedure != nil);
  794. old_size := a.cap * size_of(E);
  795. new_size := length * size_of(E);
  796. allocator := a.allocator;
  797. new_data := allocator.procedure(
  798. allocator.data, .Resize, new_size, align_of(E),
  799. a.data, old_size, 0, loc,
  800. );
  801. if new_data == nil do return false;
  802. a.data = new_data;
  803. a.len = length;
  804. a.cap = length;
  805. return true;
  806. }
  807. @builtin
  808. incl_elem :: inline proc(s: ^$S/bit_set[$E; $U], elem: E) -> S {
  809. s^ |= {elem};
  810. return s^;
  811. }
  812. @builtin
  813. incl_elems :: inline proc(s: ^$S/bit_set[$E; $U], elems: ..E) -> S {
  814. for elem in elems do s^ |= {elem};
  815. return s^;
  816. }
  817. @builtin
  818. incl_bit_set :: inline proc(s: ^$S/bit_set[$E; $U], other: S) -> S {
  819. s^ |= other;
  820. return s^;
  821. }
  822. @builtin
  823. excl_elem :: inline proc(s: ^$S/bit_set[$E; $U], elem: E) -> S {
  824. s^ &~= {elem};
  825. return s^;
  826. }
  827. @builtin
  828. excl_elems :: inline proc(s: ^$S/bit_set[$E; $U], elems: ..E) -> S {
  829. for elem in elems do s^ &~= {elem};
  830. return s^;
  831. }
  832. @builtin
  833. excl_bit_set :: inline proc(s: ^$S/bit_set[$E; $U], other: S) -> S {
  834. s^ &~= other;
  835. return s^;
  836. }
  837. @builtin incl :: proc{incl_elem, incl_elems, incl_bit_set};
  838. @builtin excl :: proc{excl_elem, excl_elems, excl_bit_set};
  839. @builtin
  840. card :: proc(s: $S/bit_set[$E; $U]) -> int {
  841. when size_of(S) == 1 {
  842. foreign { @(link_name="llvm.ctpop.i8") count_ones :: proc(i: u8) -> u8 --- }
  843. return int(count_ones(transmute(u8)s));
  844. } else when size_of(S) == 2 {
  845. foreign { @(link_name="llvm.ctpop.i16") count_ones :: proc(i: u16) -> u16 --- }
  846. return int(count_ones(transmute(u16)s));
  847. } else when size_of(S) == 4 {
  848. foreign { @(link_name="llvm.ctpop.i32") count_ones :: proc(i: u32) -> u32 --- }
  849. return int(count_ones(transmute(u32)s));
  850. } else when size_of(S) == 8 {
  851. foreign { @(link_name="llvm.ctpop.i64") count_ones :: proc(i: u64) -> u64 --- }
  852. return int(count_ones(transmute(u64)s));
  853. } else {
  854. #assert(false);
  855. return 0;
  856. }
  857. }
  858. @builtin
  859. @(disabled=ODIN_DISABLE_ASSERT)
  860. assert :: proc(condition: bool, message := "", loc := #caller_location) {
  861. if !condition {
  862. proc(message: string, loc: Source_Code_Location) {
  863. p := context.assertion_failure_proc;
  864. if p == nil {
  865. p = default_assertion_failure_proc;
  866. }
  867. p("runtime assertion", message, loc);
  868. }(message, loc);
  869. }
  870. }
  871. @builtin
  872. @(disabled=ODIN_DISABLE_ASSERT)
  873. panic :: proc(message: string, loc := #caller_location) -> ! {
  874. p := context.assertion_failure_proc;
  875. if p == nil {
  876. p = default_assertion_failure_proc;
  877. }
  878. p("panic", message, loc);
  879. }
  880. @builtin
  881. @(disabled=ODIN_DISABLE_ASSERT)
  882. unimplemented :: proc(message := "", loc := #caller_location) -> ! {
  883. p := context.assertion_failure_proc;
  884. if p == nil {
  885. p = default_assertion_failure_proc;
  886. }
  887. p("not yet implemented", message, loc);
  888. }
  889. @builtin
  890. @(disabled=ODIN_DISABLE_ASSERT)
  891. unreachable :: proc(message := "", loc := #caller_location) -> ! {
  892. p := context.assertion_failure_proc;
  893. if p == nil {
  894. p = default_assertion_failure_proc;
  895. }
  896. if message != "" {
  897. p("internal error", message, loc);
  898. } else {
  899. p("internal error", "entered unreachable code", loc);
  900. }
  901. }
  902. // Dynamic Array
  903. __dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, cap: int, loc := #caller_location) {
  904. array := (^Raw_Dynamic_Array)(array_);
  905. array.allocator = context.allocator;
  906. assert(array.allocator.procedure != nil);
  907. if cap > 0 {
  908. __dynamic_array_reserve(array_, elem_size, elem_align, cap, loc);
  909. array.len = len;
  910. }
  911. }
  912. __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap: int, loc := #caller_location) -> bool {
  913. array := (^Raw_Dynamic_Array)(array_);
  914. if cap <= array.cap do return true;
  915. if array.allocator.procedure == nil {
  916. array.allocator = context.allocator;
  917. }
  918. assert(array.allocator.procedure != nil);
  919. old_size := array.cap * elem_size;
  920. new_size := cap * elem_size;
  921. allocator := array.allocator;
  922. new_data := allocator.procedure(allocator.data, .Resize, new_size, elem_align, array.data, old_size, 0, loc);
  923. if new_data == nil do return false;
  924. array.data = new_data;
  925. array.cap = cap;
  926. return true;
  927. }
  928. __dynamic_array_resize :: proc(array_: rawptr, elem_size, elem_align: int, len: int, loc := #caller_location) -> bool {
  929. array := (^Raw_Dynamic_Array)(array_);
  930. ok := __dynamic_array_reserve(array_, elem_size, elem_align, len, loc);
  931. if ok do array.len = len;
  932. return ok;
  933. }
  934. __dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int,
  935. items: rawptr, item_count: int, loc := #caller_location) -> int {
  936. array := (^Raw_Dynamic_Array)(array_);
  937. if items == nil do return 0;
  938. if item_count <= 0 do return 0;
  939. ok := true;
  940. if array.cap <= array.len+item_count {
  941. cap := 2 * array.cap + max(8, item_count);
  942. ok = __dynamic_array_reserve(array, elem_size, elem_align, cap, loc);
  943. }
  944. // TODO(bill): Better error handling for failed reservation
  945. if !ok do return array.len;
  946. assert(array.data != nil);
  947. data := uintptr(array.data) + uintptr(elem_size*array.len);
  948. mem_copy(rawptr(data), items, elem_size * item_count);
  949. array.len += item_count;
  950. return array.len;
  951. }
  952. __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: int, loc := #caller_location) -> int {
  953. array := (^Raw_Dynamic_Array)(array_);
  954. ok := true;
  955. if array.cap <= array.len+1 {
  956. cap := 2 * array.cap + max(8, 1);
  957. ok = __dynamic_array_reserve(array, elem_size, elem_align, cap, loc);
  958. }
  959. // TODO(bill): Better error handling for failed reservation
  960. if !ok do return array.len;
  961. assert(array.data != nil);
  962. data := uintptr(array.data) + uintptr(elem_size*array.len);
  963. mem_zero(rawptr(data), elem_size);
  964. array.len += 1;
  965. return array.len;
  966. }
  967. // Map
  968. __get_map_header :: proc "contextless" (m: ^$T/map[$K]$V) -> Map_Header {
  969. header := Map_Header{m = (^Raw_Map)(m)};
  970. Entry :: struct {
  971. key: Map_Key,
  972. next: int,
  973. value: V,
  974. };
  975. header.is_key_string = intrinsics.type_is_string(K);
  976. header.entry_size = int(size_of(Entry));
  977. header.entry_align = int(align_of(Entry));
  978. header.value_offset = uintptr(offset_of(Entry, value));
  979. header.value_size = int(size_of(V));
  980. return header;
  981. }
  982. __get_map_key :: proc "contextless" (k: $K) -> Map_Key {
  983. key := k;
  984. map_key: Map_Key;
  985. T :: intrinsics.type_core_type(K);
  986. when intrinsics.type_is_integer(T) {
  987. sz :: 8*size_of(T);
  988. when sz == 8 do map_key.hash = u64(( ^u8)(&key)^);
  989. else when sz == 16 do map_key.hash = u64((^u16)(&key)^);
  990. else when sz == 32 do map_key.hash = u64((^u32)(&key)^);
  991. else when sz == 64 do map_key.hash = u64((^u64)(&key)^);
  992. else do #assert(false, "Unhandled integer size");
  993. } else when intrinsics.type_is_rune(T) {
  994. map_key.hash = u64((^rune)(&key)^);
  995. } else when intrinsics.type_is_pointer(T) {
  996. map_key.hash = u64(uintptr((^rawptr)(&key)^));
  997. } else when intrinsics.type_is_float(T) {
  998. sz :: 8*size_of(T);
  999. when sz == 32 do map_key.hash = u64((^u32)(&key)^);
  1000. else when sz == 64 do map_key.hash = u64((^u64)(&key)^);
  1001. else do #assert(false, "Unhandled float size");
  1002. } else when intrinsics.type_is_string(T) {
  1003. #assert(T == string);
  1004. str := (^string)(&key)^;
  1005. map_key.hash = default_hash_string(str);
  1006. map_key.str = str;
  1007. } else {
  1008. #assert(false, "Unhandled map key type");
  1009. }
  1010. return map_key;
  1011. }
  1012. _fnv64a :: proc(data: []byte, seed: u64 = 0xcbf29ce484222325) -> u64 {
  1013. h: u64 = seed;
  1014. for b in data {
  1015. h = (h ~ u64(b)) * 0x100000001b3;
  1016. }
  1017. return h;
  1018. }
  1019. default_hash :: proc(data: []byte) -> u64 {
  1020. return _fnv64a(data);
  1021. }
  1022. default_hash_string :: proc(s: string) -> u64 do return default_hash(transmute([]byte)(s));
  1023. source_code_location_hash :: proc(s: Source_Code_Location) -> u64 {
  1024. hash := _fnv64a(transmute([]byte)s.file_path);
  1025. hash = hash ~ (u64(s.line) * 0x100000001b3);
  1026. hash = hash ~ (u64(s.column) * 0x100000001b3);
  1027. return hash;
  1028. }
  1029. __slice_resize :: proc(array_: ^$T/[]$E, new_count: int, allocator: Allocator, loc := #caller_location) -> bool {
  1030. array := (^Raw_Slice)(array_);
  1031. if new_count < array.len do return true;
  1032. assert(allocator.procedure != nil);
  1033. old_size := array.len*size_of(T);
  1034. new_size := new_count*size_of(T);
  1035. new_data := mem_resize(array.data, old_size, new_size, align_of(T), allocator, loc);
  1036. if new_data == nil do return false;
  1037. array.data = new_data;
  1038. array.len = new_count;
  1039. return true;
  1040. }
  1041. __dynamic_map_reserve :: proc(using header: Map_Header, cap: int, loc := #caller_location) {
  1042. __dynamic_array_reserve(&m.entries, entry_size, entry_align, cap, loc);
  1043. old_len := len(m.hashes);
  1044. __slice_resize(&m.hashes, cap, m.entries.allocator, loc);
  1045. for i in old_len..<len(m.hashes) do m.hashes[i] = -1;
  1046. }
  1047. __dynamic_map_rehash :: proc(using header: Map_Header, new_count: int, loc := #caller_location) #no_bounds_check {
  1048. new_header: Map_Header = header;
  1049. nm := Raw_Map{};
  1050. nm.entries.allocator = m.entries.allocator;
  1051. new_header.m = &nm;
  1052. c := context;
  1053. if m.entries.allocator.procedure != nil {
  1054. c.allocator = m.entries.allocator;
  1055. }
  1056. context = c;
  1057. __dynamic_array_reserve(&nm.entries, entry_size, entry_align, m.entries.len, loc);
  1058. __slice_resize(&nm.hashes, new_count, m.entries.allocator, loc);
  1059. for i in 0 ..< new_count do nm.hashes[i] = -1;
  1060. for i in 0 ..< m.entries.len {
  1061. if len(nm.hashes) == 0 do __dynamic_map_grow(new_header, loc);
  1062. entry_header := __dynamic_map_get_entry(header, i);
  1063. data := uintptr(entry_header);
  1064. fr := __dynamic_map_find(new_header, entry_header.key);
  1065. j := __dynamic_map_add_entry(new_header, entry_header.key, loc);
  1066. if fr.entry_prev < 0 {
  1067. nm.hashes[fr.hash_index] = j;
  1068. } else {
  1069. e := __dynamic_map_get_entry(new_header, fr.entry_prev);
  1070. e.next = j;
  1071. }
  1072. e := __dynamic_map_get_entry(new_header, j);
  1073. e.next = fr.entry_index;
  1074. ndata := uintptr(e);
  1075. mem_copy(rawptr(ndata+value_offset), rawptr(data+value_offset), value_size);
  1076. if __dynamic_map_full(new_header) do __dynamic_map_grow(new_header, loc);
  1077. }
  1078. delete(m.hashes, m.entries.allocator, loc);
  1079. free(m.entries.data, m.entries.allocator, loc);
  1080. header.m^ = nm;
  1081. }
  1082. __dynamic_map_get :: proc(h: Map_Header, key: Map_Key) -> rawptr {
  1083. index := __dynamic_map_find(h, key).entry_index;
  1084. if index >= 0 {
  1085. data := uintptr(__dynamic_map_get_entry(h, index));
  1086. return rawptr(data + h.value_offset);
  1087. }
  1088. return nil;
  1089. }
  1090. __dynamic_map_set :: proc(h: Map_Header, key: Map_Key, value: rawptr, loc := #caller_location) #no_bounds_check {
  1091. index: int;
  1092. assert(value != nil);
  1093. if len(h.m.hashes) == 0 {
  1094. __dynamic_map_reserve(h, INITIAL_MAP_CAP, loc);
  1095. __dynamic_map_grow(h, loc);
  1096. }
  1097. fr := __dynamic_map_find(h, key);
  1098. if fr.entry_index >= 0 {
  1099. index = fr.entry_index;
  1100. } else {
  1101. index = __dynamic_map_add_entry(h, key, loc);
  1102. if fr.entry_prev >= 0 {
  1103. entry := __dynamic_map_get_entry(h, fr.entry_prev);
  1104. entry.next = index;
  1105. } else {
  1106. h.m.hashes[fr.hash_index] = index;
  1107. }
  1108. }
  1109. {
  1110. e := __dynamic_map_get_entry(h, index);
  1111. e.key = key;
  1112. val := (^byte)(uintptr(e) + h.value_offset);
  1113. mem_copy(val, value, h.value_size);
  1114. }
  1115. if __dynamic_map_full(h) {
  1116. __dynamic_map_grow(h, loc);
  1117. }
  1118. }
  1119. __dynamic_map_grow :: proc(using h: Map_Header, loc := #caller_location) {
  1120. // TODO(bill): Determine an efficient growing rate
  1121. new_count := max(4*m.entries.cap + 7, INITIAL_MAP_CAP);
  1122. __dynamic_map_rehash(h, new_count, loc);
  1123. }
  1124. __dynamic_map_full :: inline proc(using h: Map_Header) -> bool {
  1125. return int(0.75 * f64(len(m.hashes))) <= m.entries.cap;
  1126. }
  1127. __dynamic_map_hash_equal :: proc(h: Map_Header, a, b: Map_Key) -> bool {
  1128. if a.hash == b.hash {
  1129. if h.is_key_string do return a.str == b.str;
  1130. return true;
  1131. }
  1132. return false;
  1133. }
  1134. __dynamic_map_find :: proc(using h: Map_Header, key: Map_Key) -> Map_Find_Result #no_bounds_check {
  1135. fr := Map_Find_Result{-1, -1, -1};
  1136. if n := u64(len(m.hashes)); n > 0 {
  1137. fr.hash_index = int(key.hash % n);
  1138. fr.entry_index = m.hashes[fr.hash_index];
  1139. for fr.entry_index >= 0 {
  1140. entry := __dynamic_map_get_entry(h, fr.entry_index);
  1141. if __dynamic_map_hash_equal(h, entry.key, key) do return fr;
  1142. fr.entry_prev = fr.entry_index;
  1143. fr.entry_index = entry.next;
  1144. }
  1145. }
  1146. return fr;
  1147. }
  1148. __dynamic_map_add_entry :: proc(using h: Map_Header, key: Map_Key, loc := #caller_location) -> int {
  1149. prev := m.entries.len;
  1150. c := __dynamic_array_append_nothing(&m.entries, entry_size, entry_align, loc);
  1151. if c != prev {
  1152. end := __dynamic_map_get_entry(h, c-1);
  1153. end.key = key;
  1154. end.next = -1;
  1155. }
  1156. return prev;
  1157. }
  1158. __dynamic_map_delete_key :: proc(using h: Map_Header, key: Map_Key) {
  1159. fr := __dynamic_map_find(h, key);
  1160. if fr.entry_index >= 0 {
  1161. __dynamic_map_erase(h, fr);
  1162. }
  1163. }
  1164. __dynamic_map_get_entry :: proc(using h: Map_Header, index: int) -> ^Map_Entry_Header {
  1165. assert(0 <= index && index < m.entries.len);
  1166. return (^Map_Entry_Header)(uintptr(m.entries.data) + uintptr(index*entry_size));
  1167. }
  1168. __dynamic_map_erase :: proc(using h: Map_Header, fr: Map_Find_Result) #no_bounds_check {
  1169. if fr.entry_prev < 0 {
  1170. m.hashes[fr.hash_index] = __dynamic_map_get_entry(h, fr.entry_index).next;
  1171. } else {
  1172. prev := __dynamic_map_get_entry(h, fr.entry_prev);
  1173. curr := __dynamic_map_get_entry(h, fr.entry_index);
  1174. prev.next = curr.next;
  1175. }
  1176. if (fr.entry_index == m.entries.len-1) {
  1177. // NOTE(bill): No need to do anything else, just pop
  1178. } else {
  1179. old := __dynamic_map_get_entry(h, fr.entry_index);
  1180. end := __dynamic_map_get_entry(h, m.entries.len-1);
  1181. mem_copy(old, end, entry_size);
  1182. if last := __dynamic_map_find(h, old.key); last.entry_prev >= 0 {
  1183. last_entry := __dynamic_map_get_entry(h, last.entry_prev);
  1184. last_entry.next = fr.entry_index;
  1185. } else {
  1186. m.hashes[last.hash_index] = fr.entry_index;
  1187. }
  1188. }
  1189. // TODO(bill): Is this correct behaviour?
  1190. m.entries.len -= 1;
  1191. }