core.odin 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  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. //
  5. // Naming Conventions:
  6. // In general, Ada_Case for types and snake_case for values
  7. //
  8. // Package Name: snake_case (but prefer single word)
  9. // Import Name: snake_case (but prefer single word)
  10. // Types: Ada_Case
  11. // Enum Values: Ada_Case
  12. // Procedures: snake_case
  13. // Local Variables: snake_case
  14. // Constant Variables: SCREAMING_SNAKE_CASE
  15. //
  16. // IMPORTANT NOTE(bill): `type_info_of` cannot be used within a
  17. // #shared_global_scope due to the internals of the compiler.
  18. // This could change at a later date if the all these data structures are
  19. // implemented within the compiler rather than in this "preload" file
  20. //
  21. //+no-instrumentation
  22. package runtime
  23. import "base:intrinsics"
  24. // NOTE(bill): This must match the compiler's
  25. Calling_Convention :: enum u8 {
  26. Invalid = 0,
  27. Odin = 1,
  28. Contextless = 2,
  29. CDecl = 3,
  30. Std_Call = 4,
  31. Fast_Call = 5,
  32. None = 6,
  33. Naked = 7,
  34. _ = 8, // reserved
  35. Win64 = 9,
  36. SysV = 10,
  37. }
  38. Type_Info_Enum_Value :: distinct i64
  39. Platform_Endianness :: enum u8 {
  40. Platform = 0,
  41. Little = 1,
  42. Big = 2,
  43. }
  44. // Procedure type to test whether two values of the same type are equal
  45. Equal_Proc :: distinct proc "contextless" (rawptr, rawptr) -> bool
  46. // Procedure type to hash a value, default seed value is 0
  47. Hasher_Proc :: distinct proc "contextless" (data: rawptr, seed: uintptr = 0) -> uintptr
  48. Type_Info_Struct_Soa_Kind :: enum u8 {
  49. None = 0,
  50. Fixed = 1,
  51. Slice = 2,
  52. Dynamic = 3,
  53. }
  54. // Variant Types
  55. Type_Info_Named :: struct {
  56. name: string,
  57. base: ^Type_Info,
  58. pkg: string,
  59. loc: Source_Code_Location,
  60. }
  61. Type_Info_Integer :: struct {signed: bool, endianness: Platform_Endianness}
  62. Type_Info_Rune :: struct {}
  63. Type_Info_Float :: struct {endianness: Platform_Endianness}
  64. Type_Info_Complex :: struct {}
  65. Type_Info_Quaternion :: struct {}
  66. Type_Info_String :: struct {is_cstring: bool}
  67. Type_Info_Boolean :: struct {}
  68. Type_Info_Any :: struct {}
  69. Type_Info_Type_Id :: struct {}
  70. Type_Info_Pointer :: struct {
  71. elem: ^Type_Info, // nil -> rawptr
  72. }
  73. Type_Info_Multi_Pointer :: struct {
  74. elem: ^Type_Info,
  75. }
  76. Type_Info_Procedure :: struct {
  77. params: ^Type_Info, // Type_Info_Parameters
  78. results: ^Type_Info, // Type_Info_Parameters
  79. variadic: bool,
  80. convention: Calling_Convention,
  81. }
  82. Type_Info_Array :: struct {
  83. elem: ^Type_Info,
  84. elem_size: int,
  85. count: int,
  86. }
  87. Type_Info_Enumerated_Array :: struct {
  88. elem: ^Type_Info,
  89. index: ^Type_Info,
  90. elem_size: int,
  91. count: int,
  92. min_value: Type_Info_Enum_Value,
  93. max_value: Type_Info_Enum_Value,
  94. is_sparse: bool,
  95. }
  96. Type_Info_Dynamic_Array :: struct {elem: ^Type_Info, elem_size: int}
  97. Type_Info_Slice :: struct {elem: ^Type_Info, elem_size: int}
  98. Type_Info_Parameters :: struct { // Only used for procedures parameters and results
  99. types: []^Type_Info,
  100. names: []string,
  101. }
  102. Type_Info_Tuple :: Type_Info_Parameters // Will be removed eventually
  103. Type_Info_Struct :: struct {
  104. types: []^Type_Info,
  105. names: []string,
  106. offsets: []uintptr,
  107. usings: []bool,
  108. tags: []string,
  109. is_packed: bool,
  110. is_raw_union: bool,
  111. is_no_copy: bool,
  112. custom_align: bool,
  113. equal: Equal_Proc, // set only when the struct has .Comparable set but does not have .Simple_Compare set
  114. // These are only set iff this structure is an SOA structure
  115. soa_kind: Type_Info_Struct_Soa_Kind,
  116. soa_base_type: ^Type_Info,
  117. soa_len: int,
  118. }
  119. Type_Info_Union :: struct {
  120. variants: []^Type_Info,
  121. tag_offset: uintptr,
  122. tag_type: ^Type_Info,
  123. equal: Equal_Proc, // set only when the struct has .Comparable set but does not have .Simple_Compare set
  124. custom_align: bool,
  125. no_nil: bool,
  126. shared_nil: bool,
  127. }
  128. Type_Info_Enum :: struct {
  129. base: ^Type_Info,
  130. names: []string,
  131. values: []Type_Info_Enum_Value,
  132. }
  133. Type_Info_Map :: struct {
  134. key: ^Type_Info,
  135. value: ^Type_Info,
  136. map_info: ^Map_Info,
  137. }
  138. Type_Info_Bit_Set :: struct {
  139. elem: ^Type_Info,
  140. underlying: ^Type_Info, // Possibly nil
  141. lower: i64,
  142. upper: i64,
  143. }
  144. Type_Info_Simd_Vector :: struct {
  145. elem: ^Type_Info,
  146. elem_size: int,
  147. count: int,
  148. }
  149. Type_Info_Relative_Pointer :: struct {
  150. pointer: ^Type_Info, // ^T
  151. base_integer: ^Type_Info,
  152. }
  153. Type_Info_Relative_Multi_Pointer :: struct {
  154. pointer: ^Type_Info, // [^]T
  155. base_integer: ^Type_Info,
  156. }
  157. Type_Info_Matrix :: struct {
  158. elem: ^Type_Info,
  159. elem_size: int,
  160. elem_stride: int, // elem_stride >= row_count
  161. row_count: int,
  162. column_count: int,
  163. // Total element count = column_count * elem_stride
  164. layout: enum u8 {
  165. Column_Major, // array of column vectors
  166. Row_Major, // array of row vectors
  167. },
  168. }
  169. Type_Info_Soa_Pointer :: struct {
  170. elem: ^Type_Info,
  171. }
  172. Type_Info_Bit_Field :: struct {
  173. backing_type: ^Type_Info,
  174. names: []string,
  175. types: []^Type_Info,
  176. bit_sizes: []uintptr,
  177. bit_offsets: []uintptr,
  178. tags: []string,
  179. }
  180. Type_Info_Flag :: enum u8 {
  181. Comparable = 0,
  182. Simple_Compare = 1,
  183. }
  184. Type_Info_Flags :: distinct bit_set[Type_Info_Flag; u32]
  185. Type_Info :: struct {
  186. size: int,
  187. align: int,
  188. flags: Type_Info_Flags,
  189. id: typeid,
  190. variant: union {
  191. Type_Info_Named,
  192. Type_Info_Integer,
  193. Type_Info_Rune,
  194. Type_Info_Float,
  195. Type_Info_Complex,
  196. Type_Info_Quaternion,
  197. Type_Info_String,
  198. Type_Info_Boolean,
  199. Type_Info_Any,
  200. Type_Info_Type_Id,
  201. Type_Info_Pointer,
  202. Type_Info_Multi_Pointer,
  203. Type_Info_Procedure,
  204. Type_Info_Array,
  205. Type_Info_Enumerated_Array,
  206. Type_Info_Dynamic_Array,
  207. Type_Info_Slice,
  208. Type_Info_Parameters,
  209. Type_Info_Struct,
  210. Type_Info_Union,
  211. Type_Info_Enum,
  212. Type_Info_Map,
  213. Type_Info_Bit_Set,
  214. Type_Info_Simd_Vector,
  215. Type_Info_Relative_Pointer,
  216. Type_Info_Relative_Multi_Pointer,
  217. Type_Info_Matrix,
  218. Type_Info_Soa_Pointer,
  219. Type_Info_Bit_Field,
  220. },
  221. }
  222. // NOTE(bill): This must match the compiler's
  223. Typeid_Kind :: enum u8 {
  224. Invalid,
  225. Integer,
  226. Rune,
  227. Float,
  228. Complex,
  229. Quaternion,
  230. String,
  231. Boolean,
  232. Any,
  233. Type_Id,
  234. Pointer,
  235. Multi_Pointer,
  236. Procedure,
  237. Array,
  238. Enumerated_Array,
  239. Dynamic_Array,
  240. Slice,
  241. Tuple,
  242. Struct,
  243. Union,
  244. Enum,
  245. Map,
  246. Bit_Set,
  247. Simd_Vector,
  248. Relative_Pointer,
  249. Relative_Multi_Pointer,
  250. Matrix,
  251. Soa_Pointer,
  252. Bit_Field,
  253. }
  254. #assert(len(Typeid_Kind) < 32)
  255. // Typeid_Bit_Field :: bit_field #align(align_of(uintptr)) {
  256. // index: 8*size_of(uintptr) - 8,
  257. // kind: 5, // Typeid_Kind
  258. // named: 1,
  259. // special: 1, // signed, cstring, etc
  260. // reserved: 1,
  261. // }
  262. // #assert(size_of(Typeid_Bit_Field) == size_of(uintptr));
  263. // NOTE(bill): only the ones that are needed (not all types)
  264. // This will be set by the compiler
  265. type_table: []^Type_Info
  266. args__: []cstring
  267. when ODIN_OS == .Windows {
  268. // NOTE(Jeroen): If we're a Windows DLL, fwdReason will be populated.
  269. // This tells a DLL if it's first loaded, about to be unloaded, or a thread is joining/exiting.
  270. DLL_Forward_Reason :: enum u32 {
  271. Process_Detach = 0, // About to unload DLL
  272. Process_Attach = 1, // Entry point
  273. Thread_Attach = 2,
  274. Thread_Detach = 3,
  275. }
  276. dll_forward_reason: DLL_Forward_Reason
  277. }
  278. // IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
  279. Source_Code_Location :: struct {
  280. file_path: string,
  281. line, column: i32,
  282. procedure: string,
  283. }
  284. /*
  285. Used by the built-in directory `#load_directory(path: string) -> []Load_Directory_File`
  286. */
  287. Load_Directory_File :: struct {
  288. name: string,
  289. data: []byte, // immutable data
  290. }
  291. Assertion_Failure_Proc :: #type proc(prefix, message: string, loc: Source_Code_Location) -> !
  292. // Allocation Stuff
  293. Allocator_Mode :: enum byte {
  294. Alloc,
  295. Free,
  296. Free_All,
  297. Resize,
  298. Query_Features,
  299. Query_Info,
  300. Alloc_Non_Zeroed,
  301. Resize_Non_Zeroed,
  302. }
  303. Allocator_Mode_Set :: distinct bit_set[Allocator_Mode]
  304. Allocator_Query_Info :: struct {
  305. pointer: rawptr,
  306. size: Maybe(int),
  307. alignment: Maybe(int),
  308. }
  309. Allocator_Error :: enum byte {
  310. None = 0,
  311. Out_Of_Memory = 1,
  312. Invalid_Pointer = 2,
  313. Invalid_Argument = 3,
  314. Mode_Not_Implemented = 4,
  315. }
  316. Allocator_Proc :: #type proc(allocator_data: rawptr, mode: Allocator_Mode,
  317. size, alignment: int,
  318. old_memory: rawptr, old_size: int,
  319. location: Source_Code_Location = #caller_location) -> ([]byte, Allocator_Error)
  320. Allocator :: struct {
  321. procedure: Allocator_Proc,
  322. data: rawptr,
  323. }
  324. Byte :: 1
  325. Kilobyte :: 1024 * Byte
  326. Megabyte :: 1024 * Kilobyte
  327. Gigabyte :: 1024 * Megabyte
  328. Terabyte :: 1024 * Gigabyte
  329. Petabyte :: 1024 * Terabyte
  330. Exabyte :: 1024 * Petabyte
  331. // Logging stuff
  332. Logger_Level :: enum uint {
  333. Debug = 0,
  334. Info = 10,
  335. Warning = 20,
  336. Error = 30,
  337. Fatal = 40,
  338. }
  339. Logger_Option :: enum {
  340. Level,
  341. Date,
  342. Time,
  343. Short_File_Path,
  344. Long_File_Path,
  345. Line,
  346. Procedure,
  347. Terminal_Color,
  348. Thread_Id,
  349. }
  350. Logger_Options :: bit_set[Logger_Option]
  351. Logger_Proc :: #type proc(data: rawptr, level: Logger_Level, text: string, options: Logger_Options, location := #caller_location)
  352. Logger :: struct {
  353. procedure: Logger_Proc,
  354. data: rawptr,
  355. lowest_level: Logger_Level,
  356. options: Logger_Options,
  357. }
  358. Context :: struct {
  359. allocator: Allocator,
  360. temp_allocator: Allocator,
  361. assertion_failure_proc: Assertion_Failure_Proc,
  362. logger: Logger,
  363. user_ptr: rawptr,
  364. user_index: int,
  365. // Internal use only
  366. _internal: rawptr,
  367. }
  368. Raw_String :: struct {
  369. data: [^]byte,
  370. len: int,
  371. }
  372. Raw_Slice :: struct {
  373. data: rawptr,
  374. len: int,
  375. }
  376. Raw_Dynamic_Array :: struct {
  377. data: rawptr,
  378. len: int,
  379. cap: int,
  380. allocator: Allocator,
  381. }
  382. // The raw, type-erased representation of a map.
  383. //
  384. // 32-bytes on 64-bit
  385. // 16-bytes on 32-bit
  386. Raw_Map :: struct {
  387. // A single allocation spanning all keys, values, and hashes.
  388. // {
  389. // k: Map_Cell(K) * (capacity / ks_per_cell)
  390. // v: Map_Cell(V) * (capacity / vs_per_cell)
  391. // h: Map_Cell(H) * (capacity / hs_per_cell)
  392. // }
  393. //
  394. // The data is allocated assuming 64-byte alignment, meaning the address is
  395. // always a multiple of 64. This means we have 6 bits of zeros in the pointer
  396. // to store the capacity. We can store a value as large as 2^6-1 or 63 in
  397. // there. This conveniently is the maximum log2 capacity we can have for a map
  398. // as Odin uses signed integers to represent capacity.
  399. //
  400. // Since the hashes are backed by Map_Hash, which is just a 64-bit unsigned
  401. // integer, the cell structure for hashes is unnecessary because 64/8 is 8 and
  402. // requires no padding, meaning it can be indexed as a regular array of
  403. // Map_Hash directly, though for consistency sake it's written as if it were
  404. // an array of Map_Cell(Map_Hash).
  405. data: uintptr, // 8-bytes on 64-bits, 4-bytes on 32-bits
  406. len: uintptr, // 8-bytes on 64-bits, 4-bytes on 32-bits
  407. allocator: Allocator, // 16-bytes on 64-bits, 8-bytes on 32-bits
  408. }
  409. Raw_Any :: struct {
  410. data: rawptr,
  411. id: typeid,
  412. }
  413. Raw_Cstring :: struct {
  414. data: [^]byte,
  415. }
  416. Raw_Soa_Pointer :: struct {
  417. data: rawptr,
  418. index: int,
  419. }
  420. /*
  421. // Defined internally by the compiler
  422. Odin_OS_Type :: enum int {
  423. Unknown,
  424. Windows,
  425. Darwin,
  426. Linux,
  427. Essence,
  428. FreeBSD,
  429. OpenBSD,
  430. WASI,
  431. JS,
  432. Freestanding,
  433. }
  434. */
  435. Odin_OS_Type :: type_of(ODIN_OS)
  436. /*
  437. // Defined internally by the compiler
  438. Odin_Arch_Type :: enum int {
  439. Unknown,
  440. amd64,
  441. i386,
  442. arm32,
  443. arm64,
  444. wasm32,
  445. wasm64p32,
  446. }
  447. */
  448. Odin_Arch_Type :: type_of(ODIN_ARCH)
  449. /*
  450. // Defined internally by the compiler
  451. Odin_Build_Mode_Type :: enum int {
  452. Executable,
  453. Dynamic,
  454. Object,
  455. Assembly,
  456. LLVM_IR,
  457. }
  458. */
  459. Odin_Build_Mode_Type :: type_of(ODIN_BUILD_MODE)
  460. /*
  461. // Defined internally by the compiler
  462. Odin_Endian_Type :: enum int {
  463. Unknown,
  464. Little,
  465. Big,
  466. }
  467. */
  468. Odin_Endian_Type :: type_of(ODIN_ENDIAN)
  469. /*
  470. // Defined internally by the compiler
  471. Odin_Platform_Subtarget_Type :: enum int {
  472. Default,
  473. iOS,
  474. }
  475. */
  476. Odin_Platform_Subtarget_Type :: type_of(ODIN_PLATFORM_SUBTARGET)
  477. /*
  478. // Defined internally by the compiler
  479. Odin_Sanitizer_Flag :: enum u32 {
  480. Address = 0,
  481. Memory = 1,
  482. Thread = 2,
  483. }
  484. Odin_Sanitizer_Flags :: distinct bitset[Odin_Sanitizer_Flag; u32]
  485. ODIN_SANITIZER_FLAGS // is a constant
  486. */
  487. Odin_Sanitizer_Flags :: type_of(ODIN_SANITIZER_FLAGS)
  488. /////////////////////////////
  489. // Init Startup Procedures //
  490. /////////////////////////////
  491. // IMPORTANT NOTE(bill): Do not call this unless you want to explicitly set up the entry point and how it gets called
  492. // This is probably only useful for freestanding targets
  493. foreign {
  494. @(link_name="__$startup_runtime")
  495. _startup_runtime :: proc "odin" () ---
  496. @(link_name="__$cleanup_runtime")
  497. _cleanup_runtime :: proc "odin" () ---
  498. }
  499. _cleanup_runtime_contextless :: proc "contextless" () {
  500. context = default_context()
  501. _cleanup_runtime()
  502. }
  503. /////////////////////////////
  504. /////////////////////////////
  505. /////////////////////////////
  506. type_info_base :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
  507. if info == nil {
  508. return nil
  509. }
  510. base := info
  511. loop: for {
  512. #partial switch i in base.variant {
  513. case Type_Info_Named: base = i.base
  514. case: break loop
  515. }
  516. }
  517. return base
  518. }
  519. type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
  520. if info == nil {
  521. return nil
  522. }
  523. base := info
  524. loop: for {
  525. #partial switch i in base.variant {
  526. case Type_Info_Named: base = i.base
  527. case Type_Info_Enum: base = i.base
  528. case Type_Info_Bit_Field: base = i.backing_type
  529. case: break loop
  530. }
  531. }
  532. return base
  533. }
  534. type_info_base_without_enum :: type_info_core
  535. __type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check {
  536. MASK :: 1<<(8*size_of(typeid) - 8) - 1
  537. data := transmute(uintptr)id
  538. n := int(data & MASK)
  539. if n < 0 || n >= len(type_table) {
  540. n = 0
  541. }
  542. return type_table[n]
  543. }
  544. when !ODIN_NO_RTTI {
  545. typeid_base :: proc "contextless" (id: typeid) -> typeid {
  546. ti := type_info_of(id)
  547. ti = type_info_base(ti)
  548. return ti.id
  549. }
  550. typeid_core :: proc "contextless" (id: typeid) -> typeid {
  551. ti := type_info_core(type_info_of(id))
  552. return ti.id
  553. }
  554. typeid_base_without_enum :: typeid_core
  555. }
  556. debug_trap :: intrinsics.debug_trap
  557. trap :: intrinsics.trap
  558. read_cycle_counter :: intrinsics.read_cycle_counter
  559. default_logger_proc :: proc(data: rawptr, level: Logger_Level, text: string, options: Logger_Options, location := #caller_location) {
  560. // Nothing
  561. }
  562. default_logger :: proc() -> Logger {
  563. return Logger{default_logger_proc, nil, Logger_Level.Debug, nil}
  564. }
  565. default_context :: proc "contextless" () -> Context {
  566. c: Context
  567. __init_context(&c)
  568. return c
  569. }
  570. @private
  571. __init_context_from_ptr :: proc "contextless" (c: ^Context, other: ^Context) {
  572. if c == nil {
  573. return
  574. }
  575. c^ = other^
  576. __init_context(c)
  577. }
  578. @private
  579. __init_context :: proc "contextless" (c: ^Context) {
  580. if c == nil {
  581. return
  582. }
  583. // NOTE(bill): Do not initialize these procedures with a call as they are not defined with the "contextless" calling convention
  584. c.allocator.procedure = default_allocator_proc
  585. c.allocator.data = nil
  586. c.temp_allocator.procedure = default_temp_allocator_proc
  587. when !NO_DEFAULT_TEMP_ALLOCATOR {
  588. c.temp_allocator.data = &global_default_temp_allocator_data
  589. }
  590. when !ODIN_DISABLE_ASSERT {
  591. c.assertion_failure_proc = default_assertion_failure_proc
  592. }
  593. c.logger.procedure = default_logger_proc
  594. c.logger.data = nil
  595. }
  596. default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) -> ! {
  597. when ODIN_OS == .Freestanding {
  598. // Do nothing
  599. } else {
  600. when !ODIN_DISABLE_ASSERT {
  601. print_caller_location(loc)
  602. print_string(" ")
  603. }
  604. print_string(prefix)
  605. if len(message) > 0 {
  606. print_string(": ")
  607. print_string(message)
  608. }
  609. print_byte('\n')
  610. }
  611. trap()
  612. }