2 * Copyright (C) 2024, 2025 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/>.
19 private unit compiler.selfopt;
23 fn self_optimize(w : world, dir : dhandle) : world;
27 uses compiler.common.blob;
28 uses compiler.common.evaluate;
29 uses compiler.parser.unit;
30 uses compiler.parser.util;
31 uses compiler.optimize.utils;
32 uses compiler.optimize.ssa;
34 fn read_dir_recursive(d : dhandle) : list(bytes)
36 var result := empty(bytes);
37 var l := dread_lazy(d);
38 for i := 0 to len(l) do [
40 var t := stat_lazy(d, li, stat_flag_type)[0];
41 if t = stat_type_file and list_ends_with(li, ".ajla") then [
42 var str := li[ .. len(li) - 5];
45 if t = stat_type_directory then [
46 var nd := dopen_lazy(d, li, 0);
47 var dl := read_dir_recursive(nd);
48 for j := 0 to len(dl) do [
49 dl[j] := path_append(li, dl[j]);
54 result := list_sort(result);
60 functions : list(list(pcode_t));
63 fn name_to_ident(n : bytes) : bytes
66 for i := 0 to len(n) do [
67 if path_is_separator(n[i]) then [
76 fn get_inline(w : world, d : list(bytes), f : function, optimized : bool) : list(pcode_t)
78 var pc, modules := compile_module_2~save(w, d, f.un, f.program);
79 var pcode1 := pc[f.fn_idx[0]];
80 pcode1 := function_extract_nested(pcode1, f.fn_idx);
83 var pcode2 := process_pcode(pcode1, get_inline(w, d,,), sysprop(SystemProperty_Verify) <> 0);
87 fn process_nested_functions(pcode1 : list(pcode_t), get_inline : fn(function, bool) : list(pcode_t)) : list(pcode_t)
89 var pcode2 := process_pcode(pcode1, get_inline, sysprop(SystemProperty_Verify) <> 0);
90 var ptr := 9 + blob_length(pcode1[9 .. ]);
91 var pcode_to_insert := empty(pcode_t);
92 for i := 0 to pcode1[2] do [
93 var sub_pcode := pcode1[ptr + 1 .. ptr + 1 + pcode1[ptr]];
94 sub_pcode := process_nested_functions(sub_pcode, get_inline);
95 ptr += 1 + pcode1[ptr];
96 pcode_to_insert +<= len(sub_pcode);
97 pcode_to_insert += sub_pcode;
99 pcode2[2] := pcode1[2];
100 ptr := 9 + blob_length(pcode1[9 .. ]);
101 pcode2 := pcode2[ .. ptr] + pcode_to_insert + pcode2[ptr .. ];
105 fn optimize_module(w : world, d : list(bytes), u : uni, pc : list(list(pcode_t))) : uni
107 for idx := 0 to len(pc) do [
108 var pcode1 := pc[idx];
109 var pcode2 := process_nested_functions(pcode1, get_inline(w, d,,));
110 u.functions +<= pcode2;
115 fn self_optimize(implicit w : world, dir : dhandle) : world
118 var units := empty(uni);
119 var dir_nl := dopen_lazy(dir, "newlib", 0);
120 var l := read_dir_recursive(dir_nl);
121 var d := list(bytes).[ dpath_lazy(dir_nl) ];
122 for i := 0 to len(l) do [
124 for n := 0 to len(nm) do
127 var u : uni := uni.[ name : nm, functions : empty(list(pcode_t)) ];
128 var pc, modules := compile_module_2(d, u.name, false);
129 u := optimize_module(d, u, pc);
133 var a := empty(byte);
134 var module_info := empty(byte);
135 for i := 0 to len(units) do [
137 var function_info := empty(byte);
138 for j := 0 to len(u.functions) do [
139 var function := u.functions[j];
140 function_info += int_to_native(native.n_int32, len(a));
141 function_info += int_to_native(native.n_int32, len(function));
142 var lf := len(function);
144 a += int_to_native(native.n_int32, function[k]);
146 module_info += int_to_native(native.n_int32, len(a));
147 module_info += int_to_native(native.n_int32, len(u.functions));
149 a += int_to_native(native.n_int32, len(u.name));
150 for i := 0 to len(u.name) do
151 a += int_to_native(native.n_int32, u.name[i]);
153 var file_info := empty(byte);
154 file_info += int_to_native(native.n_int32, len(a));
155 file_info += int_to_native(native.n_int32, len(units));
156 file_info += int_to_native(native.n_int32, #616C6A41);
159 h := wopen(dir, "builtin.tmp", open_flag_create, open_mode_default);
161 rename(dir, "builtin.pcd", dir, "builtin.tmp");