2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
27 #ifndef wake_up_wait_list
28 void u_name(save_register_dependence
)(const char *path_name
);
29 void c_name(save_register_dependence
)(const char *path_name
);
34 const char *builtin_lib_path
;
36 static char *builtin_ptr
;
37 static size_t builtin_size
;
39 static bool builtin_mapped
;
42 struct builtin_file_info
{
48 struct builtin_module_info
{
49 uint32_t function_info
;
53 struct builtin_function_info
{
58 struct builtin_module_name
{
60 uint32_t name
[FLEXIBLE_ARRAY
];
63 #define builtin_file cast_ptr(const struct builtin_file_info *, builtin_ptr + builtin_size - sizeof(struct builtin_file_info))
65 static int builtin_compare(size_t idx
, const uint8_t *path
, size_t path_len
)
67 const struct builtin_module_info
*mod
;
68 const struct builtin_function_info
*fi
;
69 const struct builtin_module_name
*name
;
72 mod
= cast_ptr(const struct builtin_module_info
*, builtin_ptr
+ builtin_file
->module_info
);
74 fi
= cast_ptr(const struct builtin_function_info
*, builtin_ptr
+ mod
->function_info
);
75 fi
+= mod
->n_functions
;
76 name
= cast_ptr(const struct builtin_module_name
*, fi
);
78 min_len
= minimum(name
->len
, path_len
);
79 for (i
= 0; i
< min_len
; i
++) {
80 if (name
->name
[i
] < path
[i
])
82 if (name
->name
[i
] > path
[i
])
86 if (unlikely(name
->len
> path_len
))
88 if (unlikely(name
->len
< path_len
))
93 static const struct builtin_module_info
*builtin_find_module(const uint8_t *path
, size_t path_len
)
95 const struct builtin_module_info
*mod
;
98 binary_search(size_t, builtin_file
->n_modules
, s
, !(c
= builtin_compare(s
, path
, path_len
)), c
< 0, goto not_found
);
99 mod
= cast_ptr(const struct builtin_module_info
*, builtin_ptr
+ builtin_file
->module_info
);
103 internal(file_line
, "builtin_find_module: builtin module %.*s not found", (int)path_len
, path
);
107 static void builtin_walk_nested(const pcode_t
**start
, size_t *size
, size_t n_entries
, const pcode_t
*entries
)
109 while (--n_entries
) {
110 pcode_t entry
= *++entries
;
112 ajla_assert_lo(entry
< (*start
)[2], (file_line
, "builtin_walk_nested: invalid nested function: %"PRIuMAX
", %"PRIuMAX
"", (uintmax_t)entry
, (uintmax_t)(*start
)[2]));
114 ptr
+= 1 + ((*ptr
+ 3) >> 2);
123 void builtin_find_function(const uint8_t *path
, size_t path_len
, size_t n_entries
, const pcode_t
*entries
, const pcode_t
**start
, size_t *size
)
125 const struct builtin_function_info
*f
;
126 const struct builtin_module_info
*m
= builtin_find_module(path
, path_len
);
127 ajla_assert_lo((size_t)entries
[0] < m
->n_functions
, (file_line
, "builtin_find_function: invalid index"));
128 f
= cast_ptr(const struct builtin_function_info
*, builtin_ptr
+ m
->function_info
);
130 *start
= cast_ptr(const pcode_t
*, builtin_ptr
+ f
->pcode
);
132 builtin_walk_nested(start
, size
, n_entries
, entries
);
135 void builtin_init(void)
140 const char *pte
, *builtin_path
;
142 pte
= os_get_path_to_exe();
143 builtin_lib_path
= pte
;
144 builtin_path
= os_join_paths(pte
, "builtin.pcd", true, NULL
);
145 h
= os_open(os_cwd
, builtin_path
, O_RDONLY
, 0, &sink
);
146 if (unlikely(handle_is_valid(h
)))
148 mem_free(builtin_path
);
151 builtin_lib_path
= AJLA_LIB
;
152 builtin_path
= os_join_paths(AJLA_LIB
, "builtin.pcd", true, NULL
);
153 h
= os_open(os_cwd
, builtin_path
, O_RDONLY
, 0, &sink
);
154 if (unlikely(handle_is_valid(h
)))
156 mem_free(builtin_path
);
159 fatal("unable to find builtin.pcd");
162 os_fstat(h
, &st
, NULL
);
163 if (unlikely(!S_ISREG(st
.st_mode
)))
164 fatal("builtin file is not a regular file");
165 builtin_size
= (size_t)st
.st_size
;
166 if (unlikely(st
.st_size
!= (os_off_t
)builtin_size
) || unlikely(builtin_size
< sizeof(struct builtin_file_info
)) || unlikely((builtin_size
& 3) != 0))
167 fatal("builtin file has invalid size");
171 struct builtin_file_info fi
;
172 os_pread_all(h
, cast_ptr(char *, &fi
), sizeof(struct builtin_file_info
), builtin_size
- sizeof(struct builtin_file_info
), NULL
);
173 if (likely(fi
.signature
== 0x616C6A41)) {
174 void *ptr
= os_mmap(NULL
, builtin_size
, PROT_READ
, MAP_PRIVATE
, h
, 0, &sink
);
175 if (likely(ptr
!= MAP_FAILED
)) {
177 builtin_mapped
= true;
181 } else if (unlikely(fi
.signature
!= 0x416A6C61))
184 builtin_mapped
= false;
186 builtin_ptr
= mem_alloc(char *, builtin_size
);
187 os_pread_all(h
, builtin_ptr
, builtin_size
, 0, NULL
);
190 if (unlikely(builtin_file
->signature
!= 0x616C6A41)) {
192 if (unlikely(builtin_file
->signature
!= 0x416A6C61))
196 fatal("builtin file doesn't have a signature");
197 for (i
= 0; i
< builtin_size
; i
+= 4) {
198 char *p
= &builtin_ptr
[i
];
210 goto finalize
; /* avoid warning */
212 call(save_register_dependence
)(builtin_path
);
213 mem_free(builtin_path
);
216 void builtin_done(void)
219 if (likely(builtin_mapped
))
220 os_munmap(builtin_ptr
, builtin_size
, true);
224 mem_free(builtin_ptr
);