core.odin 26 KB

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