core.odin 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  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. }
  34. Type_Info_Enum_Value :: distinct i64;
  35. Platform_Endianness :: enum u8 {
  36. Platform = 0,
  37. Little = 1,
  38. Big = 2,
  39. }
  40. // Procedure type to test whether two values of the same type are equal
  41. Equal_Proc :: distinct proc "contextless" (rawptr, rawptr) -> bool;
  42. // Procedure type to hash a value, default seed value is 0
  43. Hasher_Proc :: distinct proc "contextless" (data: rawptr, seed: uintptr = 0) -> uintptr;
  44. Type_Info_Struct_Soa_Kind :: enum u8 {
  45. None = 0,
  46. Fixed = 1,
  47. Slice = 2,
  48. Dynamic = 3,
  49. }
  50. // Variant Types
  51. Type_Info_Named :: struct {
  52. name: string,
  53. base: ^Type_Info,
  54. pkg: string,
  55. loc: Source_Code_Location,
  56. };
  57. Type_Info_Integer :: struct {signed: bool, endianness: Platform_Endianness};
  58. Type_Info_Rune :: struct {};
  59. Type_Info_Float :: struct {endianness: Platform_Endianness};
  60. Type_Info_Complex :: struct {};
  61. Type_Info_Quaternion :: struct {};
  62. Type_Info_String :: struct {is_cstring: bool};
  63. Type_Info_Boolean :: struct {};
  64. Type_Info_Any :: struct {};
  65. Type_Info_Type_Id :: struct {};
  66. Type_Info_Pointer :: struct {
  67. elem: ^Type_Info, // nil -> rawptr
  68. };
  69. Type_Info_Multi_Pointer :: struct {
  70. elem: ^Type_Info,
  71. };
  72. Type_Info_Procedure :: struct {
  73. params: ^Type_Info, // Type_Info_Tuple
  74. results: ^Type_Info, // Type_Info_Tuple
  75. variadic: bool,
  76. convention: Calling_Convention,
  77. };
  78. Type_Info_Array :: struct {
  79. elem: ^Type_Info,
  80. elem_size: int,
  81. count: int,
  82. };
  83. Type_Info_Enumerated_Array :: struct {
  84. elem: ^Type_Info,
  85. index: ^Type_Info,
  86. elem_size: int,
  87. count: int,
  88. min_value: Type_Info_Enum_Value,
  89. max_value: Type_Info_Enum_Value,
  90. };
  91. Type_Info_Dynamic_Array :: struct {elem: ^Type_Info, elem_size: int};
  92. Type_Info_Slice :: struct {elem: ^Type_Info, elem_size: int};
  93. Type_Info_Tuple :: struct { // Only used for procedures parameters and results
  94. types: []^Type_Info,
  95. names: []string,
  96. };
  97. Type_Info_Struct :: struct {
  98. types: []^Type_Info,
  99. names: []string,
  100. offsets: []uintptr,
  101. usings: []bool,
  102. tags: []string,
  103. is_packed: bool,
  104. is_raw_union: bool,
  105. custom_align: bool,
  106. equal: Equal_Proc, // set only when the struct has .Comparable set but does not have .Simple_Compare set
  107. // These are only set iff this structure is an SOA structure
  108. soa_kind: Type_Info_Struct_Soa_Kind,
  109. soa_base_type: ^Type_Info,
  110. soa_len: int,
  111. };
  112. Type_Info_Union :: struct {
  113. variants: []^Type_Info,
  114. tag_offset: uintptr,
  115. tag_type: ^Type_Info,
  116. equal: Equal_Proc, // set only when the struct has .Comparable set but does not have .Simple_Compare set
  117. custom_align: bool,
  118. no_nil: bool,
  119. maybe: bool,
  120. };
  121. Type_Info_Enum :: struct {
  122. base: ^Type_Info,
  123. names: []string,
  124. values: []Type_Info_Enum_Value,
  125. };
  126. Type_Info_Map :: struct {
  127. key: ^Type_Info,
  128. value: ^Type_Info,
  129. generated_struct: ^Type_Info,
  130. key_equal: Equal_Proc,
  131. key_hasher: Hasher_Proc,
  132. };
  133. Type_Info_Bit_Set :: struct {
  134. elem: ^Type_Info,
  135. underlying: ^Type_Info, // Possibly nil
  136. lower: i64,
  137. upper: i64,
  138. };
  139. Type_Info_Simd_Vector :: struct {
  140. elem: ^Type_Info,
  141. elem_size: int,
  142. count: int,
  143. };
  144. Type_Info_Relative_Pointer :: struct {
  145. pointer: ^Type_Info,
  146. base_integer: ^Type_Info,
  147. };
  148. Type_Info_Relative_Slice :: struct {
  149. slice: ^Type_Info,
  150. base_integer: ^Type_Info,
  151. };
  152. Type_Info_Flag :: enum u8 {
  153. Comparable = 0,
  154. Simple_Compare = 1,
  155. };
  156. Type_Info_Flags :: distinct bit_set[Type_Info_Flag; u32];
  157. Type_Info :: struct {
  158. size: int,
  159. align: int,
  160. flags: Type_Info_Flags,
  161. id: typeid,
  162. variant: union {
  163. Type_Info_Named,
  164. Type_Info_Integer,
  165. Type_Info_Rune,
  166. Type_Info_Float,
  167. Type_Info_Complex,
  168. Type_Info_Quaternion,
  169. Type_Info_String,
  170. Type_Info_Boolean,
  171. Type_Info_Any,
  172. Type_Info_Type_Id,
  173. Type_Info_Pointer,
  174. Type_Info_Multi_Pointer,
  175. Type_Info_Procedure,
  176. Type_Info_Array,
  177. Type_Info_Enumerated_Array,
  178. Type_Info_Dynamic_Array,
  179. Type_Info_Slice,
  180. Type_Info_Tuple,
  181. Type_Info_Struct,
  182. Type_Info_Union,
  183. Type_Info_Enum,
  184. Type_Info_Map,
  185. Type_Info_Bit_Set,
  186. Type_Info_Simd_Vector,
  187. Type_Info_Relative_Pointer,
  188. Type_Info_Relative_Slice,
  189. },
  190. }
  191. // NOTE(bill): This must match the compiler's
  192. Typeid_Kind :: enum u8 {
  193. Invalid,
  194. Integer,
  195. Rune,
  196. Float,
  197. Complex,
  198. Quaternion,
  199. String,
  200. Boolean,
  201. Any,
  202. Type_Id,
  203. Pointer,
  204. Multi_Pointer,
  205. Procedure,
  206. Array,
  207. Enumerated_Array,
  208. Dynamic_Array,
  209. Slice,
  210. Tuple,
  211. Struct,
  212. Union,
  213. Enum,
  214. Map,
  215. Bit_Set,
  216. Simd_Vector,
  217. Relative_Pointer,
  218. Relative_Slice,
  219. }
  220. #assert(len(Typeid_Kind) < 32);
  221. // Typeid_Bit_Field :: bit_field #align align_of(uintptr) {
  222. // index: 8*size_of(uintptr) - 8,
  223. // kind: 5, // Typeid_Kind
  224. // named: 1,
  225. // special: 1, // signed, cstring, etc
  226. // reserved: 1,
  227. // }
  228. // #assert(size_of(Typeid_Bit_Field) == size_of(uintptr));
  229. // NOTE(bill): only the ones that are needed (not all types)
  230. // This will be set by the compiler
  231. type_table: []Type_Info;
  232. args__: []cstring;
  233. // IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
  234. Source_Code_Location :: struct {
  235. file_path: string,
  236. line, column: i32,
  237. procedure: string,
  238. }
  239. Assertion_Failure_Proc :: #type proc(prefix, message: string, loc: Source_Code_Location) -> !;
  240. // Allocation Stuff
  241. Allocator_Mode :: enum byte {
  242. Alloc,
  243. Free,
  244. Free_All,
  245. Resize,
  246. Query_Features,
  247. Query_Info,
  248. }
  249. Allocator_Mode_Set :: distinct bit_set[Allocator_Mode];
  250. Allocator_Query_Info :: struct {
  251. pointer: rawptr,
  252. size: Maybe(int),
  253. alignment: Maybe(int),
  254. }
  255. Allocator_Error :: enum byte {
  256. None = 0,
  257. Out_Of_Memory = 1,
  258. Invalid_Pointer = 2,
  259. Invalid_Argument = 3,
  260. Mode_Not_Implemented = 4,
  261. }
  262. Allocator_Proc :: #type proc(allocator_data: rawptr, mode: Allocator_Mode,
  263. size, alignment: int,
  264. old_memory: rawptr, old_size: int,
  265. location: Source_Code_Location = #caller_location) -> ([]byte, Allocator_Error);
  266. Allocator :: struct {
  267. procedure: Allocator_Proc,
  268. data: rawptr,
  269. }
  270. // Logging stuff
  271. Logger_Level :: enum uint {
  272. Debug = 0,
  273. Info = 10,
  274. Warning = 20,
  275. Error = 30,
  276. Fatal = 40,
  277. }
  278. Logger_Option :: enum {
  279. Level,
  280. Date,
  281. Time,
  282. Short_File_Path,
  283. Long_File_Path,
  284. Line,
  285. Procedure,
  286. Terminal_Color,
  287. Thread_Id,
  288. }
  289. Logger_Options :: bit_set[Logger_Option];
  290. Logger_Proc :: #type proc(data: rawptr, level: Logger_Level, text: string, options: Logger_Options, location := #caller_location);
  291. Logger :: struct {
  292. procedure: Logger_Proc,
  293. data: rawptr,
  294. lowest_level: Logger_Level,
  295. options: Logger_Options,
  296. }
  297. Context :: struct {
  298. allocator: Allocator,
  299. temp_allocator: Allocator,
  300. assertion_failure_proc: Assertion_Failure_Proc,
  301. logger: Logger,
  302. user_data: any,
  303. user_ptr: rawptr,
  304. user_index: int,
  305. // Internal use only
  306. _internal: rawptr,
  307. }
  308. Raw_String :: struct {
  309. data: [^]byte,
  310. len: int,
  311. }
  312. Raw_Slice :: struct {
  313. data: rawptr,
  314. len: int,
  315. }
  316. Raw_Dynamic_Array :: struct {
  317. data: rawptr,
  318. len: int,
  319. cap: int,
  320. allocator: Allocator,
  321. }
  322. Raw_Map :: struct {
  323. hashes: []int,
  324. entries: Raw_Dynamic_Array,
  325. }
  326. /////////////////////////////
  327. // Init Startup Procedures //
  328. /////////////////////////////
  329. // IMPORTANT NOTE(bill): Do not call this unless you want to explicitly set up the entry point and how it gets called
  330. // This is probably only useful for freestanding targets
  331. foreign {
  332. @(link_name="__$startup_runtime")
  333. _startup_runtime :: proc "contextless" () ---
  334. }
  335. /////////////////////////////
  336. /////////////////////////////
  337. /////////////////////////////
  338. type_info_base :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
  339. if info == nil {
  340. return nil;
  341. }
  342. base := info;
  343. loop: for {
  344. #partial switch i in base.variant {
  345. case Type_Info_Named: base = i.base;
  346. case: break loop;
  347. }
  348. }
  349. return base;
  350. }
  351. type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
  352. if info == nil {
  353. return nil;
  354. }
  355. base := info;
  356. loop: for {
  357. #partial switch i in base.variant {
  358. case Type_Info_Named: base = i.base;
  359. case Type_Info_Enum: base = i.base;
  360. case: break loop;
  361. }
  362. }
  363. return base;
  364. }
  365. type_info_base_without_enum :: type_info_core;
  366. __type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check {
  367. MASK :: 1<<(8*size_of(typeid) - 8) - 1;
  368. data := transmute(uintptr)id;
  369. n := int(data & MASK);
  370. if n < 0 || n >= len(type_table) {
  371. n = 0;
  372. }
  373. return &type_table[n];
  374. }
  375. typeid_base :: proc "contextless" (id: typeid) -> typeid {
  376. ti := type_info_of(id);
  377. ti = type_info_base(ti);
  378. return ti.id;
  379. }
  380. typeid_core :: proc "contextless" (id: typeid) -> typeid {
  381. ti := type_info_core(type_info_of(id));
  382. return ti.id;
  383. }
  384. typeid_base_without_enum :: typeid_core;
  385. debug_trap :: intrinsics.debug_trap;
  386. trap :: intrinsics.trap;
  387. read_cycle_counter :: intrinsics.read_cycle_counter;
  388. default_logger_proc :: proc(data: rawptr, level: Logger_Level, text: string, options: Logger_Options, location := #caller_location) {
  389. // Nothing
  390. }
  391. default_logger :: proc() -> Logger {
  392. return Logger{default_logger_proc, nil, Logger_Level.Debug, nil};
  393. }
  394. default_context :: proc "contextless" () -> Context {
  395. c: Context;
  396. __init_context(&c);
  397. return c;
  398. }
  399. @private
  400. __init_context_from_ptr :: proc "contextless" (c: ^Context, other: ^Context) {
  401. if c == nil {
  402. return;
  403. }
  404. c^ = other^;
  405. __init_context(c);
  406. }
  407. @private
  408. __init_context :: proc "contextless" (c: ^Context) {
  409. if c == nil {
  410. return;
  411. }
  412. // NOTE(bill): Do not initialize these procedures with a call as they are not defined with the "contexless" calling convention
  413. c.allocator.procedure = default_allocator_proc;
  414. c.allocator.data = nil;
  415. c.temp_allocator.procedure = default_temp_allocator_proc;
  416. c.temp_allocator.data = &global_default_temp_allocator_data;
  417. c.assertion_failure_proc = default_assertion_failure_proc;
  418. c.logger.procedure = default_logger_proc;
  419. c.logger.data = nil;
  420. }
  421. default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) -> ! {
  422. print_caller_location(loc);
  423. print_string(" ");
  424. print_string(prefix);
  425. if len(message) > 0 {
  426. print_string(": ");
  427. print_string(message);
  428. }
  429. print_byte('\n');
  430. // intrinsics.debug_trap();
  431. intrinsics.trap();
  432. }