core.odin 14 KB

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