core.odin 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763
  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 "intrinsics"
  6. _ :: 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 u8 {
  23. Invalid = 0,
  24. Odin = 1,
  25. Contextless = 2,
  26. Pure = 3,
  27. CDecl = 4,
  28. Std_Call = 5,
  29. Fast_Call = 6,
  30. None = 7,
  31. Pure_None = 8,
  32. }
  33. Type_Info_Enum_Value :: distinct i64;
  34. Platform_Endianness :: enum u8 {
  35. Platform = 0,
  36. Little = 1,
  37. Big = 2,
  38. }
  39. Type_Info_Struct_Soa_Kind :: enum u8 {
  40. None = 0,
  41. Fixed = 1,
  42. Slice = 2,
  43. Dynamic = 3,
  44. }
  45. // Variant Types
  46. Type_Info_Named :: struct {name: string, base: ^Type_Info};
  47. Type_Info_Integer :: struct {signed: bool, endianness: Platform_Endianness};
  48. Type_Info_Rune :: struct {};
  49. Type_Info_Float :: struct {endianness: Platform_Endianness};
  50. Type_Info_Complex :: struct {};
  51. Type_Info_Quaternion :: struct {};
  52. Type_Info_String :: struct {is_cstring: bool};
  53. Type_Info_Boolean :: struct {};
  54. Type_Info_Any :: struct {};
  55. Type_Info_Type_Id :: struct {};
  56. Type_Info_Pointer :: struct {
  57. elem: ^Type_Info, // nil -> rawptr
  58. };
  59. Type_Info_Procedure :: struct {
  60. params: ^Type_Info, // Type_Info_Tuple
  61. results: ^Type_Info, // Type_Info_Tuple
  62. variadic: bool,
  63. convention: Calling_Convention,
  64. };
  65. Type_Info_Array :: struct {
  66. elem: ^Type_Info,
  67. elem_size: int,
  68. count: int,
  69. };
  70. Type_Info_Enumerated_Array :: struct {
  71. elem: ^Type_Info,
  72. index: ^Type_Info,
  73. elem_size: int,
  74. count: int,
  75. min_value: Type_Info_Enum_Value,
  76. max_value: Type_Info_Enum_Value,
  77. };
  78. Type_Info_Dynamic_Array :: struct {elem: ^Type_Info, elem_size: int};
  79. Type_Info_Slice :: struct {elem: ^Type_Info, elem_size: int};
  80. Type_Info_Tuple :: struct { // Only really used for procedures
  81. types: []^Type_Info,
  82. names: []string,
  83. };
  84. Type_Info_Struct :: struct {
  85. types: []^Type_Info,
  86. names: []string,
  87. offsets: []uintptr,
  88. usings: []bool,
  89. tags: []string,
  90. is_packed: bool,
  91. is_raw_union: bool,
  92. custom_align: bool,
  93. // These are only set iff this structure is an SOA structure
  94. soa_kind: Type_Info_Struct_Soa_Kind,
  95. soa_base_type: ^Type_Info,
  96. soa_len: int,
  97. };
  98. Type_Info_Union :: struct {
  99. variants: []^Type_Info,
  100. tag_offset: uintptr,
  101. tag_type: ^Type_Info,
  102. custom_align: bool,
  103. no_nil: bool,
  104. maybe: 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_Relative_Pointer :: struct {
  137. pointer: ^Type_Info,
  138. base_integer: ^Type_Info,
  139. };
  140. Type_Info_Relative_Slice :: struct {
  141. slice: ^Type_Info,
  142. base_integer: ^Type_Info,
  143. };
  144. Type_Info :: struct {
  145. size: int,
  146. align: int,
  147. id: typeid,
  148. variant: union {
  149. Type_Info_Named,
  150. Type_Info_Integer,
  151. Type_Info_Rune,
  152. Type_Info_Float,
  153. Type_Info_Complex,
  154. Type_Info_Quaternion,
  155. Type_Info_String,
  156. Type_Info_Boolean,
  157. Type_Info_Any,
  158. Type_Info_Type_Id,
  159. Type_Info_Pointer,
  160. Type_Info_Procedure,
  161. Type_Info_Array,
  162. Type_Info_Enumerated_Array,
  163. Type_Info_Dynamic_Array,
  164. Type_Info_Slice,
  165. Type_Info_Tuple,
  166. Type_Info_Struct,
  167. Type_Info_Union,
  168. Type_Info_Enum,
  169. Type_Info_Map,
  170. Type_Info_Bit_Field,
  171. Type_Info_Bit_Set,
  172. Type_Info_Opaque,
  173. Type_Info_Simd_Vector,
  174. Type_Info_Relative_Pointer,
  175. Type_Info_Relative_Slice,
  176. },
  177. }
  178. // NOTE(bill): This must match the compiler's
  179. Typeid_Kind :: enum u8 {
  180. Invalid,
  181. Integer,
  182. Rune,
  183. Float,
  184. Complex,
  185. Quaternion,
  186. String,
  187. Boolean,
  188. Any,
  189. Type_Id,
  190. Pointer,
  191. Procedure,
  192. Array,
  193. Enumerated_Array,
  194. Dynamic_Array,
  195. Slice,
  196. Tuple,
  197. Struct,
  198. Union,
  199. Enum,
  200. Map,
  201. Bit_Field,
  202. Bit_Set,
  203. Opaque,
  204. Simd_Vector,
  205. Relative_Pointer,
  206. Relative_Slice,
  207. }
  208. #assert(len(Typeid_Kind) < 32);
  209. Typeid_Bit_Field :: bit_field #align align_of(uintptr) {
  210. index: 8*size_of(uintptr) - 8,
  211. kind: 5, // Typeid_Kind
  212. named: 1,
  213. special: 1, // signed, cstring, etc
  214. reserved: 1,
  215. }
  216. #assert(size_of(Typeid_Bit_Field) == size_of(uintptr));
  217. // NOTE(bill): only the ones that are needed (not all types)
  218. // This will be set by the compiler
  219. type_table: []Type_Info;
  220. args__: []cstring;
  221. // IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
  222. @builtin
  223. Maybe :: union(T: typeid) #maybe {T};
  224. Source_Code_Location :: struct {
  225. file_path: string,
  226. line, column: int,
  227. procedure: string,
  228. hash: u64,
  229. }
  230. Assertion_Failure_Proc :: #type proc(prefix, message: string, loc: Source_Code_Location);
  231. // Allocation Stuff
  232. Allocator_Mode :: enum byte {
  233. Alloc,
  234. Free,
  235. Free_All,
  236. Resize,
  237. Query_Features,
  238. Query_Info,
  239. }
  240. Allocator_Mode_Set :: distinct bit_set[Allocator_Mode];
  241. Allocator_Query_Info :: struct {
  242. pointer: rawptr,
  243. size: Maybe(int),
  244. alignment: Maybe(int),
  245. }
  246. Allocator_Proc :: #type proc(allocator_data: rawptr, mode: Allocator_Mode,
  247. size, alignment: int,
  248. old_memory: rawptr, old_size: int, flags: u64 = 0, location: Source_Code_Location = #caller_location) -> rawptr;
  249. Allocator :: struct {
  250. procedure: Allocator_Proc,
  251. data: rawptr,
  252. }
  253. // Logging stuff
  254. Logger_Level :: enum uint {
  255. Debug = 0,
  256. Info = 10,
  257. Warning = 20,
  258. Error = 30,
  259. Fatal = 40,
  260. }
  261. Logger_Option :: enum {
  262. Level,
  263. Date,
  264. Time,
  265. Short_File_Path,
  266. Long_File_Path,
  267. Line,
  268. Procedure,
  269. Terminal_Color,
  270. Thread_Id,
  271. }
  272. Logger_Options :: bit_set[Logger_Option];
  273. Logger_Proc :: #type proc(data: rawptr, level: Logger_Level, text: string, options: Logger_Options, location := #caller_location);
  274. Logger :: struct {
  275. procedure: Logger_Proc,
  276. data: rawptr,
  277. lowest_level: Logger_Level,
  278. options: Logger_Options,
  279. }
  280. Context :: struct {
  281. allocator: Allocator,
  282. temp_allocator: Allocator,
  283. assertion_failure_proc: Assertion_Failure_Proc,
  284. logger: Logger,
  285. thread_id: int,
  286. user_data: any,
  287. user_ptr: rawptr,
  288. user_index: int,
  289. }
  290. Raw_String :: struct {
  291. data: ^byte,
  292. len: int,
  293. }
  294. Raw_Slice :: struct {
  295. data: rawptr,
  296. len: int,
  297. }
  298. Raw_Dynamic_Array :: struct {
  299. data: rawptr,
  300. len: int,
  301. cap: int,
  302. allocator: Allocator,
  303. }
  304. Raw_Map :: struct {
  305. hashes: []int,
  306. entries: Raw_Dynamic_Array,
  307. }
  308. INITIAL_MAP_CAP :: 16;
  309. Map_Key :: struct {
  310. hash: u64,
  311. /* NOTE(bill)
  312. size_of(Map_Key) == 16 Bytes on 32-bit systems
  313. size_of(Map_Key) == 24 Bytes on 64-bit systems
  314. This does mean that an extra word is wasted for each map when a string is not used on 64-bit systems
  315. however, this is probably not a huge problem in terms of memory usage
  316. */
  317. key: struct #raw_union {
  318. str: string,
  319. val: u64,
  320. },
  321. }
  322. Map_Find_Result :: struct {
  323. hash_index: int,
  324. entry_prev: int,
  325. entry_index: int,
  326. }
  327. Map_Entry_Header :: struct {
  328. key: Map_Key,
  329. next: int,
  330. /*
  331. value: Value_Type,
  332. */
  333. }
  334. Map_Header :: struct {
  335. m: ^Raw_Map,
  336. is_key_string: bool,
  337. entry_size: int,
  338. entry_align: int,
  339. value_offset: uintptr,
  340. value_size: int,
  341. }
  342. /////////////////////////////
  343. // Init Startup Procedures //
  344. /////////////////////////////
  345. // IMPORTANT NOTE(bill): Do not call this unless you want to explicitly set up the entry point and how it gets called
  346. // This is probably only useful for freestanding targets
  347. foreign {
  348. @(link_name="__$startup_runtime")
  349. _startup_runtime :: proc "contextless" () ---
  350. }
  351. /////////////////////////////
  352. /////////////////////////////
  353. /////////////////////////////
  354. type_info_base :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
  355. if info == nil {
  356. return nil;
  357. }
  358. base := info;
  359. loop: for {
  360. #partial switch i in base.variant {
  361. case Type_Info_Named: base = i.base;
  362. case: break loop;
  363. }
  364. }
  365. return base;
  366. }
  367. type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
  368. if info == nil {
  369. return nil;
  370. }
  371. base := info;
  372. loop: for {
  373. #partial switch i in base.variant {
  374. case Type_Info_Named: base = i.base;
  375. case Type_Info_Enum: base = i.base;
  376. case Type_Info_Opaque: base = i.elem;
  377. case: break loop;
  378. }
  379. }
  380. return base;
  381. }
  382. type_info_base_without_enum :: type_info_core;
  383. __type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info {
  384. data := transmute(Typeid_Bit_Field)id;
  385. n := int(data.index);
  386. if n < 0 || n >= len(type_table) {
  387. n = 0;
  388. }
  389. return &type_table[n];
  390. }
  391. typeid_base :: proc "contextless" (id: typeid) -> typeid {
  392. ti := type_info_of(id);
  393. ti = type_info_base(ti);
  394. return ti.id;
  395. }
  396. typeid_core :: proc "contextless" (id: typeid) -> typeid {
  397. ti := type_info_base_without_enum(type_info_of(id));
  398. return ti.id;
  399. }
  400. typeid_base_without_enum :: typeid_core;
  401. @(default_calling_convention = "none")
  402. foreign {
  403. @(link_name="llvm.assume")
  404. assume :: proc(cond: bool) ---;
  405. @(link_name="llvm.debugtrap")
  406. debug_trap :: proc() ---;
  407. @(link_name="llvm.trap")
  408. trap :: proc() -> ! ---;
  409. @(link_name="llvm.readcyclecounter")
  410. read_cycle_counter :: proc() -> u64 ---;
  411. }
  412. default_logger_proc :: proc(data: rawptr, level: Logger_Level, text: string, options: Logger_Options, location := #caller_location) {
  413. // Nothing
  414. }
  415. default_logger :: proc() -> Logger {
  416. return Logger{default_logger_proc, nil, Logger_Level.Debug, nil};
  417. }
  418. default_context :: proc "contextless" () -> Context {
  419. c: Context;
  420. __init_context(&c);
  421. return c;
  422. }
  423. @private
  424. __init_context_from_ptr :: proc "contextless" (c: ^Context, other: ^Context) {
  425. if c == nil {
  426. return;
  427. }
  428. c^ = other^;
  429. __init_context(c);
  430. }
  431. @private
  432. __init_context :: proc "contextless" (c: ^Context) {
  433. if c == nil {
  434. return;
  435. }
  436. // NOTE(bill): Do not initialize these procedures with a call as they are not defined with the "contexless" calling convention
  437. c.allocator.procedure = default_allocator_proc;
  438. c.allocator.data = nil;
  439. c.temp_allocator.procedure = default_temp_allocator_proc;
  440. c.temp_allocator.data = &global_default_temp_allocator_data;
  441. c.thread_id = current_thread_id(); // NOTE(bill): This is "contextless" so it is okay to call
  442. c.assertion_failure_proc = default_assertion_failure_proc;
  443. c.logger.procedure = default_logger_proc;
  444. c.logger.data = nil;
  445. }
  446. @thread_local global_default_temp_allocator_data: Default_Temp_Allocator;
  447. @builtin
  448. init_global_temporary_allocator :: proc(size: int, backup_allocator := context.allocator) {
  449. default_temp_allocator_init(&global_default_temp_allocator_data, size, backup_allocator);
  450. }
  451. default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) {
  452. print_caller_location(loc);
  453. print_string(" ");
  454. print_string(prefix);
  455. if len(message) > 0 {
  456. print_string(": ");
  457. print_string(message);
  458. }
  459. print_byte('\n');
  460. debug_trap();
  461. }
  462. @builtin
  463. copy_slice :: proc "contextless" (dst, src: $T/[]$E) -> int {
  464. n := max(0, min(len(dst), len(src)));
  465. if n > 0 {
  466. mem_copy(raw_data(dst), raw_data(src), n*size_of(E));
  467. }
  468. return n;
  469. }
  470. @builtin
  471. copy_from_string :: proc "contextless" (dst: $T/[]$E/u8, src: $S/string) -> int {
  472. n := max(0, min(len(dst), len(src)));
  473. if n > 0 {
  474. mem_copy(raw_data(dst), raw_data(src), n);
  475. }
  476. return n;
  477. }
  478. @builtin
  479. copy :: proc{copy_slice, copy_from_string};
  480. @builtin
  481. unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) {
  482. bounds_check_error_loc(loc, index, len(array));
  483. n := len(array)-1;
  484. if index != n {
  485. array[index] = array[n];
  486. }
  487. pop(array);
  488. }
  489. @builtin
  490. ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) {
  491. bounds_check_error_loc(loc, index, len(array));
  492. if index+1 < len(array) {
  493. copy(array[index:], array[index+1:]);
  494. }
  495. pop(array);
  496. }
  497. @builtin
  498. remove_range :: proc(array: ^$D/[dynamic]$T, lo, hi: int, loc := #caller_location) {
  499. slice_expr_error_lo_hi_loc(loc, lo, hi, len(array));
  500. n := max(hi-lo, 0);
  501. if n > 0 {
  502. if hi != len(array) {
  503. copy(array[lo:], array[hi:]);
  504. }
  505. (^Raw_Dynamic_Array)(array).len -= n;
  506. }
  507. }
  508. @builtin
  509. pop :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check {
  510. assert(len(array) > 0, "", loc);
  511. res = array[len(array)-1];
  512. (^Raw_Dynamic_Array)(array).len -= 1;
  513. return res;
  514. }
  515. @builtin
  516. pop_safe :: proc(array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check {
  517. if len(array) == 0 {
  518. return;
  519. }
  520. res, ok = array[len(array)-1], true;
  521. (^Raw_Dynamic_Array)(array).len -= 1;
  522. return;
  523. }
  524. @builtin
  525. pop_front :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check {
  526. assert(len(array) > 0, "", loc);
  527. res = array[0];
  528. if len(array) > 1 {
  529. copy(array[0:], array[1:]);
  530. }
  531. (^Raw_Dynamic_Array)(array).len -= 1;
  532. return res;
  533. }
  534. @builtin
  535. pop_front_safe :: proc(array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check {
  536. if len(array) == 0 {
  537. return;
  538. }
  539. res, ok = array[0], true;
  540. if len(array) > 1 {
  541. copy(array[0:], array[1:]);
  542. }
  543. (^Raw_Dynamic_Array)(array).len -= 1;
  544. return;
  545. }
  546. @builtin
  547. clear :: proc{clear_dynamic_array, clear_map};
  548. @builtin
  549. reserve :: proc{reserve_dynamic_array, reserve_map};
  550. @builtin
  551. resize :: proc{resize_dynamic_array};
  552. @builtin
  553. free :: proc{mem_free};
  554. @builtin
  555. free_all :: proc{mem_free_all};
  556. @builtin
  557. delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) {
  558. mem_free(raw_data(str), allocator, loc);
  559. }
  560. @builtin
  561. delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) {
  562. mem_free((^byte)(str), allocator, loc);
  563. }
  564. @builtin
  565. delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) {
  566. mem_free(raw_data(array), array.allocator, loc);
  567. }
  568. @builtin
  569. delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) {
  570. mem_free(raw_data(array), allocator, loc);
  571. }
  572. @builtin
  573. delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) {
  574. raw := transmute(Raw_Map)m;
  575. delete_slice(raw.hashes);
  576. mem_free(raw.entries.data, raw.entries.allocator, loc);
  577. }
  578. @builtin
  579. delete :: proc{
  580. delete_string,
  581. delete_cstring,
  582. delete_dynamic_array,
  583. delete_slice,
  584. delete_map,
  585. };
  586. @builtin
  587. new :: inline proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> ^T {
  588. ptr := (^T)(mem_alloc(size_of(T), align_of(T), allocator, loc));
  589. if ptr != nil { ptr^ = T{}; }
  590. return ptr;
  591. }
  592. @builtin
  593. new_clone :: inline proc(data: $T, allocator := context.allocator, loc := #caller_location) -> ^T {
  594. ptr := (^T)(mem_alloc(size_of(T), align_of(T), allocator, loc));
  595. if ptr != nil { ptr^ = data; }
  596. return ptr;
  597. }
  598. make_aligned :: proc($T: typeid/[]$E, auto_cast len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> T {
  599. make_slice_error_loc(loc, len);
  600. data := mem_alloc(size_of(E)*len, alignment, allocator, loc);
  601. if data == nil && size_of(E) != 0 {
  602. return nil;
  603. }
  604. // mem_zero(data, size_of(E)*len);
  605. s := Raw_Slice{data, len};
  606. return transmute(T)s;
  607. }
  608. @builtin
  609. make_slice :: inline proc($T: typeid/[]$E, auto_cast len: int, allocator := context.allocator, loc := #caller_location) -> T {
  610. return make_aligned(T, len, align_of(E), allocator, loc);
  611. }
  612. @builtin
  613. make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> T {
  614. return make_dynamic_array_len_cap(T, 0, 16, allocator, loc);
  615. }
  616. @builtin
  617. make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, auto_cast len: int, allocator := context.allocator, loc := #caller_location) -> T {
  618. return make_dynamic_array_len_cap(T, len, len, allocator, loc);
  619. }
  620. @builtin
  621. 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 {
  622. make_dynamic_array_error_loc(loc, len, cap);
  623. data := mem_alloc(size_of(E)*cap, align_of(E), allocator, loc);
  624. s := Raw_Dynamic_Array{data, len, cap, allocator};
  625. if data == nil && size_of(E) != 0 {
  626. s.len, s.cap = 0, 0;
  627. }
  628. // mem_zero(data, size_of(E)*cap);
  629. return transmute(T)s;
  630. }
  631. @builtin
  632. make_map :: proc($T: typeid/map[$K]$E, auto_cast cap: int = 16, allocator := context.allocator, loc := #caller_location) -> T {
  633. make_map_expr_error_loc(loc, cap);
  634. context.allocator = allocator;
  635. m: T;
  636. reserve_map(&m, cap);
  637. return m;
  638. }
  639. @builtin
  640. make :: proc{
  641. make_slice,
  642. make_dynamic_array,
  643. make_dynamic_array_len,
  644. make_dynamic_array_len_cap,
  645. make_map,
  646. };
  647. @builtin
  648. clear_map :: inline proc "contextless" (m: ^$T/map[$K]$V) {
  649. if m == nil {
  650. return;
  651. }
  652. raw_map := (^Raw_Map)(m);
  653. entries := (^Raw_Dynamic_Array)(&raw_map.entries);
  654. entries.len = 0;
  655. for _, i in raw_map.hashes {
  656. raw_map.hashes[i] = -1;
  657. }
  658. }
  659. @builtin
  660. reserve_map :: proc(m: ^$T/map[$K]$V, capacity: int) {
  661. if m != nil {
  662. __dynamic_map_reserve(__get_map_header(m), capacity);
  663. }
  664. }
  665. @builtin
  666. delete_key :: proc(m: ^$T/map[$K]$V, key: K) {
  667. if m != nil {
  668. __dynamic_map_delete_key(__get_map_header(m), __get_map_key(key));
  669. }
  670. }
  671. @builtin
  672. append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) {
  673. if array == nil {
  674. return;
  675. }
  676. arg_len := 1;
  677. if cap(array) < len(array)+arg_len {
  678. cap := 2 * cap(array) + max(8, arg_len);
  679. _ = reserve(array, cap, loc);
  680. }
  681. arg_len = min(cap(array)-len(array), arg_len);
  682. if arg_len > 0 {
  683. a := (^Raw_Dynamic_Array)(array);
  684. if size_of(E) != 0 {
  685. data := (^E)(a.data);
  686. assert(data != nil);
  687. val := arg;
  688. mem_copy(ptr_offset(data, a.len), &val, size_of(E));
  689. }
  690. a.len += arg_len;
  691. }
  692. }
  693. @builtin
  694. append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) {
  695. if array == nil {
  696. return;
  697. }
  698. arg_len := len(args);
  699. if arg_len <= 0 {
  700. return;
  701. }
  702. if cap(array) < len(array)+arg_len {
  703. cap := 2 * cap(array) + max(8, arg_len);
  704. _ = reserve(array, cap, loc);
  705. }
  706. arg_len = min(cap(array)-len(array), arg_len);
  707. if arg_len > 0 {
  708. a := (^Raw_Dynamic_Array)(array);
  709. if size_of(E) != 0 {
  710. data := (^E)(a.data);
  711. assert(data != nil);
  712. mem_copy(ptr_offset(data, a.len), &args[0], size_of(E) * arg_len);
  713. }
  714. a.len += arg_len;
  715. }
  716. }
  717. @builtin
  718. append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) {
  719. args := transmute([]E)arg;
  720. append_elems(array=array, args=args, loc=loc);
  721. }
  722. @builtin
  723. reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_location) -> bool {
  724. if array == nil {
  725. return false;
  726. }
  727. old_cap := cap(array);
  728. if capacity <= old_cap {
  729. return true;
  730. }
  731. if array.allocator.procedure == nil {
  732. array.allocator = context.allocator;
  733. }
  734. assert(array.allocator.procedure != nil);
  735. ti := type_info_of(typeid_of(T));
  736. ti = type_info_base(ti);
  737. si := &ti.variant.(Type_Info_Struct);
  738. field_count := uintptr(len(si.offsets) - 3);
  739. if field_count == 0 {
  740. return true;
  741. }
  742. cap_ptr := cast(^int)rawptr(uintptr(array) + (field_count + 1)*size_of(rawptr));
  743. assert(cap_ptr^ == old_cap);
  744. old_size := 0;
  745. new_size := 0;
  746. max_align := 0;
  747. for i in 0..<field_count {
  748. type := si.types[i].variant.(Type_Info_Pointer).elem;
  749. max_align = max(max_align, type.align);
  750. old_size = align_forward_int(old_size, type.align);
  751. new_size = align_forward_int(new_size, type.align);
  752. old_size += type.size * old_cap;
  753. new_size += type.size * capacity;
  754. }
  755. old_size = align_forward_int(old_size, max_align);
  756. new_size = align_forward_int(new_size, max_align);
  757. old_data := (^rawptr)(array)^;
  758. new_data := array.allocator.procedure(
  759. array.allocator.data, .Alloc, new_size, max_align,
  760. nil, old_size, 0, loc,
  761. );
  762. if new_data == nil {
  763. return false;
  764. }
  765. cap_ptr^ = capacity;
  766. old_offset := 0;
  767. new_offset := 0;
  768. for i in 0..<field_count {
  769. type := si.types[i].variant.(Type_Info_Pointer).elem;
  770. max_align = max(max_align, type.align);
  771. old_offset = align_forward_int(old_offset, type.align);
  772. new_offset = align_forward_int(new_offset, type.align);
  773. new_data_elem := rawptr(uintptr(new_data) + uintptr(new_offset));
  774. old_data_elem := rawptr(uintptr(old_data) + uintptr(old_offset));
  775. mem_copy(new_data_elem, old_data_elem, type.size * old_cap);
  776. (^rawptr)(uintptr(array) + i*size_of(rawptr))^ = new_data_elem;
  777. old_offset += type.size * old_cap;
  778. new_offset += type.size * capacity;
  779. }
  780. array.allocator.procedure(
  781. array.allocator.data, .Free, 0, max_align,
  782. old_data, old_size, 0, loc,
  783. );
  784. return true;
  785. }
  786. @builtin
  787. append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, arg: E, loc := #caller_location) {
  788. if array == nil {
  789. return;
  790. }
  791. arg_len := 1;
  792. if cap(array) <= len(array)+arg_len {
  793. cap := 2 * cap(array) + max(8, arg_len);
  794. _ = reserve_soa(array, cap, loc);
  795. }
  796. arg_len = min(cap(array)-len(array), arg_len);
  797. if arg_len > 0 {
  798. ti := type_info_of(typeid_of(T));
  799. ti = type_info_base(ti);
  800. si := &ti.variant.(Type_Info_Struct);
  801. field_count := uintptr(len(si.offsets) - 3);
  802. if field_count == 0 {
  803. return;
  804. }
  805. data := (^rawptr)(array)^;
  806. len_ptr := cast(^int)rawptr(uintptr(array) + (field_count + 0)*size_of(rawptr));
  807. soa_offset := 0;
  808. item_offset := 0;
  809. arg_copy := arg;
  810. arg_ptr := &arg_copy;
  811. max_align := 0;
  812. for i in 0..<field_count {
  813. type := si.types[i].variant.(Type_Info_Pointer).elem;
  814. max_align = max(max_align, type.align);
  815. soa_offset = align_forward_int(soa_offset, type.align);
  816. item_offset = align_forward_int(item_offset, type.align);
  817. dst := rawptr(uintptr(data) + uintptr(soa_offset) + uintptr(type.size * len_ptr^));
  818. src := rawptr(uintptr(arg_ptr) + uintptr(item_offset));
  819. mem_copy(dst, src, type.size);
  820. soa_offset += type.size * cap(array);
  821. item_offset += type.size;
  822. }
  823. len_ptr^ += arg_len;
  824. }
  825. }
  826. @builtin
  827. append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_location) {
  828. if array == nil {
  829. return;
  830. }
  831. arg_len := len(args);
  832. if arg_len == 0 {
  833. return;
  834. }
  835. if cap(array) <= len(array)+arg_len {
  836. cap := 2 * cap(array) + max(8, arg_len);
  837. _ = reserve_soa(array, cap, loc);
  838. }
  839. arg_len = min(cap(array)-len(array), arg_len);
  840. if arg_len > 0 {
  841. ti := type_info_of(typeid_of(T));
  842. ti = type_info_base(ti);
  843. si := &ti.variant.(Type_Info_Struct);
  844. field_count := uintptr(len(si.offsets) - 3);
  845. if field_count == 0 {
  846. return;
  847. }
  848. data := (^rawptr)(array)^;
  849. len_ptr := cast(^int)rawptr(uintptr(array) + (field_count + 0)*size_of(rawptr));
  850. soa_offset := 0;
  851. item_offset := 0;
  852. args_ptr := &args[0];
  853. max_align := 0;
  854. for i in 0..<field_count {
  855. type := si.types[i].variant.(Type_Info_Pointer).elem;
  856. max_align = max(max_align, type.align);
  857. soa_offset = align_forward_int(soa_offset, type.align);
  858. item_offset = align_forward_int(item_offset, type.align);
  859. dst := uintptr(data) + uintptr(soa_offset) + uintptr(type.size * len_ptr^);
  860. src := uintptr(args_ptr) + uintptr(item_offset);
  861. for j in 0..<arg_len {
  862. d := rawptr(dst + uintptr(j*type.size));
  863. s := rawptr(src + uintptr(j*size_of(E)));
  864. mem_copy(d, s, type.size);
  865. }
  866. soa_offset += type.size * cap(array);
  867. item_offset += type.size;
  868. }
  869. len_ptr^ += arg_len;
  870. }
  871. }
  872. @builtin
  873. append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) {
  874. for arg in args {
  875. append(array = array, args = transmute([]E)(arg), loc = loc);
  876. }
  877. }
  878. @builtin append :: proc{append_elem, append_elems, append_elem_string};
  879. @builtin append_soa :: proc{append_soa_elem, append_soa_elems};
  880. @builtin
  881. append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) {
  882. if array == nil {
  883. return;
  884. }
  885. resize(array, len(array)+1);
  886. }
  887. @builtin
  888. insert_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #caller_location) -> (ok: bool) #no_bounds_check {
  889. if array == nil {
  890. return;
  891. }
  892. n := len(array);
  893. m :: 1;
  894. resize(array, n+m, loc);
  895. if n+m <= len(array) {
  896. when size_of(E) != 0 {
  897. copy(array[index+m:], array[index:]);
  898. array[index] = arg;
  899. }
  900. ok = true;
  901. }
  902. return;
  903. }
  904. @builtin
  905. insert_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #caller_location) -> (ok: bool) #no_bounds_check {
  906. if array == nil {
  907. return;
  908. }
  909. if len(args) == 0 {
  910. ok = true;
  911. return;
  912. }
  913. n := len(array);
  914. m := len(args);
  915. resize(array, n+m, loc);
  916. if n+m <= len(array) {
  917. when size_of(E) != 0 {
  918. copy(array[index+m:], array[index:]);
  919. copy(array[index:], args);
  920. }
  921. ok = true;
  922. }
  923. return;
  924. }
  925. @builtin
  926. insert_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string, loc := #caller_location) -> (ok: bool) #no_bounds_check {
  927. if array == nil {
  928. return;
  929. }
  930. if len(args) == 0 {
  931. ok = true;
  932. return;
  933. }
  934. n := len(array);
  935. m := len(args);
  936. resize(array, n+m, loc);
  937. if n+m <= len(array) {
  938. copy(array[index+m:], array[index:]);
  939. copy(array[index:], args);
  940. ok = true;
  941. }
  942. return;
  943. }
  944. @builtin insert_at :: proc{insert_at_elem, insert_at_elems, insert_at_elem_string};
  945. @builtin
  946. clear_dynamic_array :: inline proc "contextless" (array: ^$T/[dynamic]$E) {
  947. if array != nil {
  948. (^Raw_Dynamic_Array)(array).len = 0;
  949. }
  950. }
  951. @builtin
  952. reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> bool {
  953. if array == nil {
  954. return false;
  955. }
  956. a := (^Raw_Dynamic_Array)(array);
  957. if capacity <= a.cap {
  958. return true;
  959. }
  960. if a.allocator.procedure == nil {
  961. a.allocator = context.allocator;
  962. }
  963. assert(a.allocator.procedure != nil);
  964. old_size := a.cap * size_of(E);
  965. new_size := capacity * size_of(E);
  966. allocator := a.allocator;
  967. new_data := allocator.procedure(
  968. allocator.data, .Resize, new_size, align_of(E),
  969. a.data, old_size, 0, loc,
  970. );
  971. if new_data == nil {
  972. return false;
  973. }
  974. a.data = new_data;
  975. a.cap = capacity;
  976. return true;
  977. }
  978. @builtin
  979. resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> bool {
  980. if array == nil {
  981. return false;
  982. }
  983. a := (^Raw_Dynamic_Array)(array);
  984. if length <= a.cap {
  985. a.len = max(length, 0);
  986. return true;
  987. }
  988. if a.allocator.procedure == nil {
  989. a.allocator = context.allocator;
  990. }
  991. assert(a.allocator.procedure != nil);
  992. old_size := a.cap * size_of(E);
  993. new_size := length * size_of(E);
  994. allocator := a.allocator;
  995. new_data := allocator.procedure(
  996. allocator.data, .Resize, new_size, align_of(E),
  997. a.data, old_size, 0, loc,
  998. );
  999. if new_data == nil {
  1000. return false;
  1001. }
  1002. a.data = new_data;
  1003. a.len = length;
  1004. a.cap = length;
  1005. return true;
  1006. }
  1007. @builtin
  1008. incl_elem :: inline proc(s: ^$S/bit_set[$E; $U], elem: E) -> S {
  1009. s^ |= {elem};
  1010. return s^;
  1011. }
  1012. @builtin
  1013. incl_elems :: inline proc(s: ^$S/bit_set[$E; $U], elems: ..E) -> S {
  1014. for elem in elems {
  1015. s^ |= {elem};
  1016. }
  1017. return s^;
  1018. }
  1019. @builtin
  1020. incl_bit_set :: inline proc(s: ^$S/bit_set[$E; $U], other: S) -> S {
  1021. s^ |= other;
  1022. return s^;
  1023. }
  1024. @builtin
  1025. excl_elem :: inline proc(s: ^$S/bit_set[$E; $U], elem: E) -> S {
  1026. s^ &~= {elem};
  1027. return s^;
  1028. }
  1029. @builtin
  1030. excl_elems :: inline proc(s: ^$S/bit_set[$E; $U], elems: ..E) -> S {
  1031. for elem in elems {
  1032. s^ &~= {elem};
  1033. }
  1034. return s^;
  1035. }
  1036. @builtin
  1037. excl_bit_set :: inline proc(s: ^$S/bit_set[$E; $U], other: S) -> S {
  1038. s^ &~= other;
  1039. return s^;
  1040. }
  1041. @builtin incl :: proc{incl_elem, incl_elems, incl_bit_set};
  1042. @builtin excl :: proc{excl_elem, excl_elems, excl_bit_set};
  1043. @builtin
  1044. card :: proc(s: $S/bit_set[$E; $U]) -> int {
  1045. when size_of(S) == 1 {
  1046. foreign { @(link_name="llvm.ctpop.i8") count_ones :: proc(i: u8) -> u8 --- }
  1047. return int(count_ones(transmute(u8)s));
  1048. } else when size_of(S) == 2 {
  1049. foreign { @(link_name="llvm.ctpop.i16") count_ones :: proc(i: u16) -> u16 --- }
  1050. return int(count_ones(transmute(u16)s));
  1051. } else when size_of(S) == 4 {
  1052. foreign { @(link_name="llvm.ctpop.i32") count_ones :: proc(i: u32) -> u32 --- }
  1053. return int(count_ones(transmute(u32)s));
  1054. } else when size_of(S) == 8 {
  1055. foreign { @(link_name="llvm.ctpop.i64") count_ones :: proc(i: u64) -> u64 --- }
  1056. return int(count_ones(transmute(u64)s));
  1057. } else when size_of(S) == 16 {
  1058. foreign { @(link_name="llvm.ctpop.i128") count_ones :: proc(i: u128) -> u128 --- }
  1059. return int(count_ones(transmute(u128)s));
  1060. } else {
  1061. #panic("Unhandled card bit_set size");
  1062. }
  1063. }
  1064. @builtin
  1065. raw_array_data :: proc "contextless" (a: $P/^($T/[$N]$E)) -> ^E {
  1066. return (^E)(a);
  1067. }
  1068. @builtin
  1069. raw_slice_data :: proc "contextless" (s: $S/[]$E) -> ^E {
  1070. ptr := (transmute(Raw_Slice)s).data;
  1071. return (^E)(ptr);
  1072. }
  1073. @builtin
  1074. raw_dynamic_array_data :: proc "contextless" (s: $S/[dynamic]$E) -> ^E {
  1075. ptr := (transmute(Raw_Dynamic_Array)s).data;
  1076. return (^E)(ptr);
  1077. }
  1078. @builtin
  1079. raw_string_data :: proc "contextless" (s: $S/string) -> ^u8 {
  1080. return (transmute(Raw_String)s).data;
  1081. }
  1082. @builtin
  1083. raw_data :: proc{raw_array_data, raw_slice_data, raw_dynamic_array_data, raw_string_data};
  1084. @builtin
  1085. @(disabled=ODIN_DISABLE_ASSERT)
  1086. assert :: proc(condition: bool, message := "", loc := #caller_location) {
  1087. if !condition {
  1088. proc(message: string, loc: Source_Code_Location) {
  1089. p := context.assertion_failure_proc;
  1090. if p == nil {
  1091. p = default_assertion_failure_proc;
  1092. }
  1093. p("runtime assertion", message, loc);
  1094. }(message, loc);
  1095. }
  1096. }
  1097. @builtin
  1098. @(disabled=ODIN_DISABLE_ASSERT)
  1099. panic :: proc(message: string, loc := #caller_location) -> ! {
  1100. p := context.assertion_failure_proc;
  1101. if p == nil {
  1102. p = default_assertion_failure_proc;
  1103. }
  1104. p("panic", message, loc);
  1105. }
  1106. @builtin
  1107. @(disabled=ODIN_DISABLE_ASSERT)
  1108. unimplemented :: proc(message := "", loc := #caller_location) -> ! {
  1109. p := context.assertion_failure_proc;
  1110. if p == nil {
  1111. p = default_assertion_failure_proc;
  1112. }
  1113. p("not yet implemented", message, loc);
  1114. }
  1115. @builtin
  1116. @(disabled=ODIN_DISABLE_ASSERT)
  1117. unreachable :: proc(message := "", loc := #caller_location) -> ! {
  1118. p := context.assertion_failure_proc;
  1119. if p == nil {
  1120. p = default_assertion_failure_proc;
  1121. }
  1122. if message != "" {
  1123. p("internal error", message, loc);
  1124. } else {
  1125. p("internal error", "entered unreachable code", loc);
  1126. }
  1127. }
  1128. // Dynamic Array
  1129. __dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, cap: int, loc := #caller_location) {
  1130. array := (^Raw_Dynamic_Array)(array_);
  1131. array.allocator = context.allocator;
  1132. assert(array.allocator.procedure != nil);
  1133. if cap > 0 {
  1134. __dynamic_array_reserve(array_, elem_size, elem_align, cap, loc);
  1135. array.len = len;
  1136. }
  1137. }
  1138. __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap: int, loc := #caller_location) -> bool {
  1139. array := (^Raw_Dynamic_Array)(array_);
  1140. // NOTE(tetra, 2020-01-26): We set the allocator before earlying-out below, because user code is usually written
  1141. // assuming that appending/reserving will set the allocator, if it is not already set.
  1142. if array.allocator.procedure == nil {
  1143. array.allocator = context.allocator;
  1144. }
  1145. assert(array.allocator.procedure != nil);
  1146. if cap <= array.cap {
  1147. return true;
  1148. }
  1149. old_size := array.cap * elem_size;
  1150. new_size := cap * elem_size;
  1151. allocator := array.allocator;
  1152. new_data := allocator.procedure(allocator.data, .Resize, new_size, elem_align, array.data, old_size, 0, loc);
  1153. if new_data != nil || elem_size == 0 {
  1154. array.data = new_data;
  1155. array.cap = cap;
  1156. return true;
  1157. }
  1158. return false;
  1159. }
  1160. __dynamic_array_resize :: proc(array_: rawptr, elem_size, elem_align: int, len: int, loc := #caller_location) -> bool {
  1161. array := (^Raw_Dynamic_Array)(array_);
  1162. ok := __dynamic_array_reserve(array_, elem_size, elem_align, len, loc);
  1163. if ok {
  1164. array.len = len;
  1165. }
  1166. return ok;
  1167. }
  1168. __dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int,
  1169. items: rawptr, item_count: int, loc := #caller_location) -> int {
  1170. array := (^Raw_Dynamic_Array)(array_);
  1171. if items == nil {
  1172. return 0;
  1173. }
  1174. if item_count <= 0 {
  1175. return 0;
  1176. }
  1177. ok := true;
  1178. if array.cap <= array.len+item_count {
  1179. cap := 2 * array.cap + max(8, item_count);
  1180. ok = __dynamic_array_reserve(array, elem_size, elem_align, cap, loc);
  1181. }
  1182. // TODO(bill): Better error handling for failed reservation
  1183. if !ok {
  1184. return array.len;
  1185. }
  1186. assert(array.data != nil);
  1187. data := uintptr(array.data) + uintptr(elem_size*array.len);
  1188. mem_copy(rawptr(data), items, elem_size * item_count);
  1189. array.len += item_count;
  1190. return array.len;
  1191. }
  1192. __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: int, loc := #caller_location) -> int {
  1193. array := (^Raw_Dynamic_Array)(array_);
  1194. ok := true;
  1195. if array.cap <= array.len+1 {
  1196. cap := 2 * array.cap + max(8, 1);
  1197. ok = __dynamic_array_reserve(array, elem_size, elem_align, cap, loc);
  1198. }
  1199. // TODO(bill): Better error handling for failed reservation
  1200. if !ok {
  1201. return array.len;
  1202. }
  1203. assert(array.data != nil);
  1204. data := uintptr(array.data) + uintptr(elem_size*array.len);
  1205. mem_zero(rawptr(data), elem_size);
  1206. array.len += 1;
  1207. return array.len;
  1208. }
  1209. // Map
  1210. __get_map_header :: proc "contextless" (m: ^$T/map[$K]$V) -> Map_Header {
  1211. header := Map_Header{m = (^Raw_Map)(m)};
  1212. Entry :: struct {
  1213. key: Map_Key,
  1214. next: int,
  1215. value: V,
  1216. };
  1217. header.is_key_string = intrinsics.type_is_string(K);
  1218. header.entry_size = int(size_of(Entry));
  1219. header.entry_align = int(align_of(Entry));
  1220. header.value_offset = uintptr(offset_of(Entry, value));
  1221. header.value_size = int(size_of(V));
  1222. return header;
  1223. }
  1224. __get_map_key :: proc "contextless" (k: $K) -> Map_Key {
  1225. key := k;
  1226. map_key: Map_Key;
  1227. T :: intrinsics.type_core_type(K);
  1228. when intrinsics.type_is_integer(T) {
  1229. map_key.hash = default_hash_ptr(&key, size_of(T));
  1230. sz :: 8*size_of(T);
  1231. when sz == 8 { map_key.key.val = u64(( ^u8)(&key)^); }
  1232. else when sz == 16 { map_key.key.val = u64((^u16)(&key)^); }
  1233. else when sz == 32 { map_key.key.val = u64((^u32)(&key)^); }
  1234. else when sz == 64 { map_key.key.val = u64((^u64)(&key)^); }
  1235. else { #panic("Unhandled integer size"); }
  1236. } else when intrinsics.type_is_rune(T) {
  1237. map_key.hash = default_hash_ptr(&key, size_of(T));
  1238. map_key.key.val = u64((^rune)(&key)^);
  1239. } else when intrinsics.type_is_pointer(T) {
  1240. map_key.hash = default_hash_ptr(&key, size_of(T));
  1241. map_key.key.val = u64(uintptr((^rawptr)(&key)^));
  1242. } else when intrinsics.type_is_float(T) {
  1243. map_key.hash = default_hash_ptr(&key, size_of(T));
  1244. sz :: 8*size_of(T);
  1245. when sz == 32 { map_key.key.val = u64((^u32)(&key)^); }
  1246. else when sz == 64 { map_key.key.val = u64((^u64)(&key)^); }
  1247. else { #panic("Unhandled float size"); }
  1248. } else when intrinsics.type_is_string(T) {
  1249. #assert(T == string);
  1250. str := (^string)(&key)^;
  1251. map_key.hash = default_hash_string(str);
  1252. map_key.key.str = str;
  1253. } else {
  1254. #panic("Unhandled map key type");
  1255. }
  1256. return map_key;
  1257. }
  1258. _fnv64a :: proc "contextless" (data: []byte, seed: u64 = 0xcbf29ce484222325) -> u64 {
  1259. h: u64 = seed;
  1260. for b in data {
  1261. h = (h ~ u64(b)) * 0x100000001b3;
  1262. }
  1263. return h;
  1264. }
  1265. default_hash :: inline proc "contextless" (data: []byte) -> u64 {
  1266. return _fnv64a(data);
  1267. }
  1268. default_hash_string :: inline proc "contextless" (s: string) -> u64 {
  1269. return default_hash(transmute([]byte)(s));
  1270. }
  1271. default_hash_ptr :: inline proc "contextless" (data: rawptr, size: int) -> u64 {
  1272. s := Raw_Slice{data, size};
  1273. return default_hash(transmute([]byte)(s));
  1274. }
  1275. source_code_location_hash :: proc(s: Source_Code_Location) -> u64 {
  1276. hash := _fnv64a(transmute([]byte)s.file_path);
  1277. hash = hash ~ (u64(s.line) * 0x100000001b3);
  1278. hash = hash ~ (u64(s.column) * 0x100000001b3);
  1279. return hash;
  1280. }
  1281. __slice_resize :: proc(array_: ^$T/[]$E, new_count: int, allocator: Allocator, loc := #caller_location) -> bool {
  1282. array := (^Raw_Slice)(array_);
  1283. if new_count < array.len {
  1284. return true;
  1285. }
  1286. assert(allocator.procedure != nil);
  1287. old_size := array.len*size_of(T);
  1288. new_size := new_count*size_of(T);
  1289. new_data := mem_resize(array.data, old_size, new_size, align_of(T), allocator, loc);
  1290. if new_data == nil {
  1291. return false;
  1292. }
  1293. array.data = new_data;
  1294. array.len = new_count;
  1295. return true;
  1296. }
  1297. __dynamic_map_reserve :: proc(using header: Map_Header, cap: int, loc := #caller_location) {
  1298. __dynamic_array_reserve(&m.entries, entry_size, entry_align, cap, loc);
  1299. old_len := len(m.hashes);
  1300. __slice_resize(&m.hashes, cap, m.entries.allocator, loc);
  1301. for i in old_len..<len(m.hashes) {
  1302. m.hashes[i] = -1;
  1303. }
  1304. }
  1305. __dynamic_map_rehash :: proc(using header: Map_Header, new_count: int, loc := #caller_location) #no_bounds_check {
  1306. new_header: Map_Header = header;
  1307. nm := Raw_Map{};
  1308. nm.entries.allocator = m.entries.allocator;
  1309. new_header.m = &nm;
  1310. c := context;
  1311. if m.entries.allocator.procedure != nil {
  1312. c.allocator = m.entries.allocator;
  1313. }
  1314. context = c;
  1315. __dynamic_array_reserve(&nm.entries, entry_size, entry_align, m.entries.len, loc);
  1316. __slice_resize(&nm.hashes, new_count, m.entries.allocator, loc);
  1317. for i in 0 ..< new_count {
  1318. nm.hashes[i] = -1;
  1319. }
  1320. for i in 0 ..< m.entries.len {
  1321. if len(nm.hashes) == 0 {
  1322. __dynamic_map_grow(new_header, loc);
  1323. }
  1324. entry_header := __dynamic_map_get_entry(header, i);
  1325. data := uintptr(entry_header);
  1326. fr := __dynamic_map_find(new_header, entry_header.key);
  1327. j := __dynamic_map_add_entry(new_header, entry_header.key, loc);
  1328. if fr.entry_prev < 0 {
  1329. nm.hashes[fr.hash_index] = j;
  1330. } else {
  1331. e := __dynamic_map_get_entry(new_header, fr.entry_prev);
  1332. e.next = j;
  1333. }
  1334. e := __dynamic_map_get_entry(new_header, j);
  1335. e.next = fr.entry_index;
  1336. ndata := uintptr(e);
  1337. mem_copy(rawptr(ndata+value_offset), rawptr(data+value_offset), value_size);
  1338. if __dynamic_map_full(new_header) {
  1339. __dynamic_map_grow(new_header, loc);
  1340. }
  1341. }
  1342. delete(m.hashes, m.entries.allocator, loc);
  1343. free(m.entries.data, m.entries.allocator, loc);
  1344. header.m^ = nm;
  1345. }
  1346. __dynamic_map_get :: proc(h: Map_Header, key: Map_Key) -> rawptr {
  1347. index := __dynamic_map_find(h, key).entry_index;
  1348. if index >= 0 {
  1349. data := uintptr(__dynamic_map_get_entry(h, index));
  1350. return rawptr(data + h.value_offset);
  1351. }
  1352. return nil;
  1353. }
  1354. __dynamic_map_set :: proc(h: Map_Header, key: Map_Key, value: rawptr, loc := #caller_location) #no_bounds_check {
  1355. index: int;
  1356. assert(value != nil);
  1357. if len(h.m.hashes) == 0 {
  1358. __dynamic_map_reserve(h, INITIAL_MAP_CAP, loc);
  1359. __dynamic_map_grow(h, loc);
  1360. }
  1361. fr := __dynamic_map_find(h, key);
  1362. if fr.entry_index >= 0 {
  1363. index = fr.entry_index;
  1364. } else {
  1365. index = __dynamic_map_add_entry(h, key, loc);
  1366. if fr.entry_prev >= 0 {
  1367. entry := __dynamic_map_get_entry(h, fr.entry_prev);
  1368. entry.next = index;
  1369. } else {
  1370. h.m.hashes[fr.hash_index] = index;
  1371. }
  1372. }
  1373. {
  1374. e := __dynamic_map_get_entry(h, index);
  1375. e.key = key;
  1376. val := (^byte)(uintptr(e) + h.value_offset);
  1377. mem_copy(val, value, h.value_size);
  1378. }
  1379. if __dynamic_map_full(h) {
  1380. __dynamic_map_grow(h, loc);
  1381. }
  1382. }
  1383. __dynamic_map_grow :: proc(using h: Map_Header, loc := #caller_location) {
  1384. // TODO(bill): Determine an efficient growing rate
  1385. new_count := max(4*m.entries.cap + 7, INITIAL_MAP_CAP);
  1386. __dynamic_map_rehash(h, new_count, loc);
  1387. }
  1388. __dynamic_map_full :: inline proc(using h: Map_Header) -> bool {
  1389. return int(0.75 * f64(len(m.hashes))) <= m.entries.cap;
  1390. }
  1391. __dynamic_map_hash_equal :: proc(h: Map_Header, a, b: Map_Key) -> bool {
  1392. if a.hash == b.hash {
  1393. if h.is_key_string {
  1394. return a.key.str == b.key.str;
  1395. } else {
  1396. return a.key.val == b.key.val;
  1397. }
  1398. return true;
  1399. }
  1400. return false;
  1401. }
  1402. __dynamic_map_find :: proc(using h: Map_Header, key: Map_Key) -> Map_Find_Result #no_bounds_check {
  1403. fr := Map_Find_Result{-1, -1, -1};
  1404. if n := u64(len(m.hashes)); n > 0 {
  1405. fr.hash_index = int(key.hash % n);
  1406. fr.entry_index = m.hashes[fr.hash_index];
  1407. for fr.entry_index >= 0 {
  1408. entry := __dynamic_map_get_entry(h, fr.entry_index);
  1409. if __dynamic_map_hash_equal(h, entry.key, key) {
  1410. return fr;
  1411. }
  1412. fr.entry_prev = fr.entry_index;
  1413. fr.entry_index = entry.next;
  1414. }
  1415. }
  1416. return fr;
  1417. }
  1418. __dynamic_map_add_entry :: proc(using h: Map_Header, key: Map_Key, loc := #caller_location) -> int {
  1419. prev := m.entries.len;
  1420. c := __dynamic_array_append_nothing(&m.entries, entry_size, entry_align, loc);
  1421. if c != prev {
  1422. end := __dynamic_map_get_entry(h, c-1);
  1423. end.key = key;
  1424. end.next = -1;
  1425. }
  1426. return prev;
  1427. }
  1428. __dynamic_map_delete_key :: proc(using h: Map_Header, key: Map_Key) {
  1429. fr := __dynamic_map_find(h, key);
  1430. if fr.entry_index >= 0 {
  1431. __dynamic_map_erase(h, fr);
  1432. }
  1433. }
  1434. __dynamic_map_get_entry :: proc(using h: Map_Header, index: int) -> ^Map_Entry_Header {
  1435. assert(0 <= index && index < m.entries.len);
  1436. return (^Map_Entry_Header)(uintptr(m.entries.data) + uintptr(index*entry_size));
  1437. }
  1438. __dynamic_map_erase :: proc(using h: Map_Header, fr: Map_Find_Result) #no_bounds_check {
  1439. if fr.entry_prev < 0 {
  1440. m.hashes[fr.hash_index] = __dynamic_map_get_entry(h, fr.entry_index).next;
  1441. } else {
  1442. prev := __dynamic_map_get_entry(h, fr.entry_prev);
  1443. curr := __dynamic_map_get_entry(h, fr.entry_index);
  1444. prev.next = curr.next;
  1445. }
  1446. if (fr.entry_index == m.entries.len-1) {
  1447. // NOTE(bill): No need to do anything else, just pop
  1448. } else {
  1449. old := __dynamic_map_get_entry(h, fr.entry_index);
  1450. end := __dynamic_map_get_entry(h, m.entries.len-1);
  1451. mem_copy(old, end, entry_size);
  1452. if last := __dynamic_map_find(h, old.key); last.entry_prev >= 0 {
  1453. last_entry := __dynamic_map_get_entry(h, last.entry_prev);
  1454. last_entry.next = fr.entry_index;
  1455. } else {
  1456. m.hashes[last.hash_index] = fr.entry_index;
  1457. }
  1458. }
  1459. // TODO(bill): Is this correct behaviour?
  1460. m.entries.len -= 1;
  1461. }