code.c
1 //! @file code.c
2 //! @author J. Marcel van der Veer
3 //
4 //! @section Copyright
5 //
6 // This file is part of VIF - vintage FORTRAN compiler.
7 // Copyright 2020-2024 J. Marcel van der Veer <algol68g@xs4all.nl>.
8 //
9 //! @section License
10 //
11 // This program is free software; you can redistribute it and/or modify it
12 // under the terms of the GNU General Public License as published by the
13 // Free Software Foundation; either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful, but
17 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 // more details. You should have received a copy of the GNU General Public
20 // License along with this program. If not, see <http://www.gnu.org/licenses/>.
21
22 //! @section Synopsis
23 //!
24 //! Routines to emit C object code.
25
26 #include <vif.h>
27
28 #undef LIST_IMPLICIT
29
30 #define MAX_UNIQ_STR 5000
31 static char *uniq_str[MAX_UNIQ_STR];
32 static int_4 uniq_index[MAX_UNIQ_STR];
33 static int_4 n_uniq_str = 0;
34 static int_4 n_dc = 0;
35
36 int_4 code_uniq_str (char *nstr)
37 {
38 int_4 k;
39 for (k = 0; k < n_uniq_str; k++) {
40 if (strcmp (nstr, uniq_str[k]) == 0) {
41 return uniq_index[k];
42 }
43 }
44 if (k == MAX_UNIQ_STR) {
45 OVERFLOW (501, "code_uniq_str");
46 }
47 RECORD idf, str;
48 int_4 rc = n_dc;
49 uniq_index[n_uniq_str] = rc;
50 _srecordf (idf, "_dc_%d", n_dc++);
51 _srecordf (str, "#define %s %s", idf, nstr);
52 code (0, STRINGS, str);
53 code (0, STRINGS, "\n");
54 uniq_str[n_uniq_str++] = stralloc (nstr);
55 return rc;
56 }
57
58 char *get_uniq_str (char *dc, char *buf)
59 {
60 for (int_4 k = 0; k < n_uniq_str; k++) {
61 RECORD idf;
62 _srecordf (idf, "_dc_%d", uniq_index[k]);
63 if (strcmp (idf, dc) == 0) {
64 int_4 j;
65 for (j = 1; j < strlen (uniq_str[k]) - 1; j++) {
66 buf[j - 1] = uniq_str[k][j];
67 }
68 buf[j] = '\0';
69 return buf;
70 }
71 }
72 return NULL;
73 }
74
75 int_4 code_real_32_const (char *num)
76 {
77 RECORD str;
78 int_4 rc = n_dc;
79 _srecordf (str, "real_32 _dc_%d = { // %s\n", n_dc++, curlex);
80 code (0, CONSTANTS, str);
81 real_32 x = atox (num);
82 for (int_4 k = 0; k <= FLT256_LEN; k++) {
83 if (k < FLT256_LEN) {
84 _srecordf (str, "0x%04x,", (x.value)[k]);
85 } else {
86 _srecordf (str, "0x%04x", (x.value)[k]);
87 }
88 code (0, CONSTANTS, str);
89 if ((k + 1) % 4 == 0) {
90 code (0, CONSTANTS, "\n");
91 }
92 }
93 code (0, CONSTANTS, "};");
94 code (0, CONSTANTS, "\n");
95 code (0, CONSTANTS, "\n");
96 return rc;
97 }
98
99 int_4 code (int_4 proc, int_4 phase, char *str)
100 {
101 if (n_c_src >= MAX_C_SRC) {
102 MAX_C_SRC += INCREMENT;
103 object = (C_SRC *) f_realloc (object, MAX_C_SRC * sizeof (C_SRC));
104 }
105 // Add to list.
106 C_SRC *lin = &object[n_c_src];
107 int_4 patch = n_c_src;
108 lin->text = stralloc (str);
109 lin->phase = phase;
110 lin->proc = proc;
111 n_c_src++;
112 return patch;
113 }
114
115 void cpp_direct (int_4 proc, int_4 lin, int_4 phase)
116 {
117 if (!gcc_ftn_lines) {
118 return;
119 }
120 if (source[lin].cpp == FALSE) {
121 RECORD str;
122 char *q = source[lin].text;
123 if (q != NULL) {
124 for (int_4 k = 0; q[k] != '\0' && k < 5; k++) {
125 q++;
126 }
127 while (q[0] != '\0' && q[0] == ' ') {
128 q++;
129 }
130 RECORD edit;
131 int_4 n = 0, m = 0;
132 while (q[n] != '\0') {
133 if (q[n] == '"') {
134 edit[m++] = '\\';
135 } else if (q[n] == '%') {
136 edit[m++] = '%';
137 }
138 edit[m++] = q[n++];
139 }
140 edit[m] = '\0';
141 RECORD loc;
142 _srecordf (loc, "** %-10s ** isn %d %s", modnam, source[lin].isn, edit);
143 _srecordf (str, "# line %d \"%s\"", source[lin].num, loc);
144 code (proc, phase, str);
145 if (trace) {
146 _srecordf (str, "~fprintf (stderr, \"%s\\n\");", loc);
147 code (proc, phase, str);
148 code (proc, phase, "\n");
149 }
150 }
151 source[lin].cpp = TRUE;
152 }
153 }
154
155 static int_4 idf_code (IDENT *idf, int_4 save, int_4 src)
156 {
157 // Must we declare this identifier?
158 if (idf == NULL) {
159 return FALSE; // Oops!
160 }
161 if (idf->mode.save != save || idf->source != src) {
162 return FALSE; // Wrong category
163 }
164 if (idf->parm != NULL) {
165 return FALSE; // Parameter to subprogram
166 }
167 if (idf->external || idf->intrinsic) {
168 return FALSE; // Otherwise declared
169 }
170 if (idf->nest > 0) {
171 return FALSE; // Macro parameter, declared inline
172 }
173 return TRUE;
174 }
175
176 void code_one_type (IDENT * table, int_4 M, int_4 type, int_4 len, int_4 blck, int_4 proc, int_4 save, int_4 src, int_4 phase)
177 {
178 int_4 k, N;
179 for (k = 0, N = 0; k < M; k++) {
180 IDENT *idf = &table[k];
181 if (idf_code (idf, save, src)) {
182 if (idf->const_ref) {
183 ;
184 } else if (idf->alias != NULL && idf->mode.type == type && idf->mode.len == len) {
185 N++;
186 } else if (!idf->arg && idf->mode.type == type && idf->mode.len == len && idf->common == blck) {
187 N++;
188 }
189 }
190 }
191 if (N > 0) {
192 RECORD str;
193 MODE mode = (MODE) {.type = type,.len = len,.dim = 0 };
194 if (table == locals && (save == STATIC && src == SOURCE)) {
195 _srecordf (str, "static %s ", wtype (&mode, NOARG, NOFUN));
196 } else {
197 _srecordf (str, "%s ", wtype (&mode, NOARG, NOFUN));
198 }
199 code (proc, phase, str);
200 for (k = 0; k < M; k++) {
201 IDENT *idf = &table[k];
202 if (idf_code (idf, save, src)) {
203 if (idf->const_ref) {
204 ;
205 } else if (idf->alias != NULL && idf->mode.type == type && idf->mode.len == len) {
206 code (proc, phase, ptr_to_array (idf, NOCONST, NOCAST, ACTUAL));
207 if (--N > 0) {
208 code (proc, phase, ", ");
209 }
210 } else if (!idf->arg && idf->mode.type == type && idf->mode.len == len && idf->common == blck) {
211 str[0] = '\0';
212 if (idf->mode.dim > 0) {
213 RECORD buf;
214 str[0] = '\0';
215 for (int_4 n = 0; n < idf->mode.dim; n++) {
216 if (EQUAL (idf->len[n], "VARY")) {
217 ERROR (502, "only argument arrays can vary", NULL);
218 buf[0] = '\0';
219 } else {
220 fold_int_4 (buf, idf->len[n]);
221 }
222 if (isint_4 (buf, NULL)) {
223 bufcat (str, buf, RECLN);
224 } else {
225 bufcat (str,"(", RECLN);
226 bufcat (str, buf, RECLN);
227 bufcat (str,")", RECLN);
228 }
229 if (n < idf->mode.dim - 1) {
230 bufcat (str, " * ", RECLN);
231 }
232 }
233 fold_int_4 (buf, str);
234 _srecordf (str, "%s[%s]", CID (idf), buf);
235 code (proc, phase, str);
236 } else {
237 code (proc, phase, CID (idf));
238 }
239 if (--N > 0) {
240 code (proc, phase, ", ");
241 }
242 }
243 }
244 }
245 code (proc, phase, ";\n");
246 }
247 }
248
249 void code_idfs (IDENT * table, int_4 M, int_4 blck, int_4 proc, int_4 phase)
250 {
251 for (int_4 n = STATIC; n <= AUTOMATIC; n++) {
252 for (int_4 m = SOURCE; m <= TEMP; m++) {
253 code_one_type (table, M, INTEGER, 2, blck, proc, n, m, phase);
254 code_one_type (table, M, INTEGER, 4, blck, proc, n, m, phase);
255 code_one_type (table, M, INTEGER, 8, blck, proc, n, m, phase);
256 code_one_type (table, M, LOGICAL, 4, blck, proc, n, m, phase);
257 code_one_type (table, M, REAL, 4, blck, proc, n, m, phase);
258 code_one_type (table, M, REAL, 8, blck, proc, n, m, phase);
259 code_one_type (table, M, REAL, 16, blck, proc, n, m, phase);
260 code_one_type (table, M, REAL, 32, blck, proc, n, m, phase);
261 code_one_type (table, M, COMPLEX, 8, blck, proc, n, m, phase);
262 code_one_type (table, M, COMPLEX, 16, blck, proc, n, m, phase);
263 code_one_type (table, M, COMPLEX, 32, blck, proc, n, m, phase);
264 code_one_type (table, M, COMPLEX, 64, blck, proc, n, m, phase);
265 for (int_4 k = 0, len = 2; k < MAX_STRLENS; k++, len *= 2) {
266 if (strlens[k]) {
267 code_one_type (table, M, CHARACTER, len - 1, blck, proc, n, m, phase);
268 }
269 }
270 }
271 }
272 }
273
274 void code_common (void)
275 {
276 int_4 k;
277 for (k = EXTERN + 1; k < ncommons; k++) {
278 RECORD name;
279 code (0, COMMON, "\n");
280 _srecordf (name, "// common /%s/\n", commons[k]);
281 code (0, COMMON, name);
282 _srecordf (name, "static struct {\n");
283 code (0, COMMON, name);
284 code_idfs (globals, nglobals, k, 0, COMMON);
285 _srecordf (name, "} %s;\n", commons[k]);
286 code (0, COMMON, name);
287 }
288 }
289
290 void code_exts (IDENT * table, int_4 M, int_4 eblck, int_4 proc, int_4 phase)
291 {
292 int_4 k;
293 (void) eblck;
294 for (k = 0; k < M; k++) {
295 IDENT *idf = &table[k];
296 if (idf->external && idf->arg == NOARG) {
297 if (!find_module (CID (idf))) { // Avoid prototype error.
298 RECORD str;
299 MODE *mode = &(idf->mode);
300 if (!idf->used) {
301 code (proc, phase, "// ");
302 }
303 _srecordf (str, "extern %s %s ();\n", wtype (mode, NOARG, NOFUN), edit_f (CID (idf)));
304 code (proc, phase, str);
305 }
306 }
307 }
308 }
309
310 void code_arrlen (IDENT * idf)
311 {
312 int_4 k, tlen = 1, npack = 0;
313 RECORD pack, str;
314 pack[0] = '\0';
315 for (k = 0; k < idf->mode.dim; k++) {
316 int_4 len;
317 if (EQUAL (idf->len[k], "VARY")) {
318 ERROR (503, "array has varying size", NULL);
319 } else if (isint_4 (idf->len[k], &len)) {
320 tlen *= len;
321 } else {
322 if (npack > 0) {
323 bufcat (pack, " * ", RECLN);
324 }
325 bufcat (pack, "(", RECLN);
326 bufcat (pack, idf->len[k], RECLN);
327 bufcat (pack, ")", RECLN);
328 npack++;
329 }
330 }
331 if (tlen == 1 && npack > 0) {
332 _srecordf (str, "%s", pack);
333 } else if (npack == 0) {
334 _srecordf (str, "%d", tlen);
335 } else {
336 _srecordf (str, "%d * %s", tlen, pack);
337 }
338 code (nprocs, BODY, str);
339 }
340
341 void proc_listing (int_4 proc)
342 {
343 int_4 k, n, l_i, l_f;
344 RECORD lin;
345 code (nprocs, SYMBOLS, newpage (modnam, "symbol-table"));
346 #if defined (LIST_IMPLICIT)
347 // Implicit modes
348 strcpy (lin, "// ");
349 for (k = ord ('a'); k <= ord ('z'); k++) {
350 RECORD str;
351 _srecordf (str, "'%c' %-12s", 'a' + k, qtype (&implic[k].mode));
352 bufcat (lin, str, RECLN);
353 if ((k + 1) % 6 == 0) {
354 bufcat (lin, "\n", RECLN);
355 code (nprocs, SYMBOLS, lin);
356 strcpy (lin, "// ");
357 }
358 }
359 code (nprocs, SYMBOLS, lin);
360 code (nprocs, SYMBOLS, "\n");
361 #endif
362 // Local variables
363 if (nlocals > 0) {
364 for (k = 0; k < nlocals; k++) {
365 IDENT *idf = &locals[k];
366 if (idf->source != SOURCE || idf->external || idf->intrinsic) {
367 continue;
368 }
369 RECORD str;
370 _srecordf (lin, "// line %6d %4s %-12s %-8s", idf->line, (idf->mode.save == STATIC ? "save" : "auto"), qtype (&idf->mode), CID (idf));
371 for (n = 0; n < idf->mode.dim; n++) {
372 _srecordf (str, " (%s, %s)", idf->lwb[n], idf->upb[n]);
373 bufcat (lin, str, RECLN);
374 }
375 if (idf->parm != NULL) {
376 bufcat (lin, " parm", RECLN);
377 } else if (idf->used) {
378 bufcat (lin, " used", RECLN);
379 } else {
380 bufcat (lin, " idle", RECLN);
381 }
382 if (idf->alias != NULL) {
383 _srecordf (str, " aliased to %s", CID (idf->alias));
384 bufcat (lin, str, RECLN);
385 }
386 if (idf->equiv != NULL) {
387 _srecordf (str, " aliased from %s", CID (idf->equiv));
388 bufcat (lin, str, RECLN);
389 }
390 if (idf->parm != NULL) {
391 _srecordf (str, " = %s", idf->parm);
392 bufcat (lin, str, RECLN);
393 }
394 code (nprocs, SYMBOLS, lin);
395 }
396 code (nprocs, SYMBOLS, "\n");
397 }
398 if (nlabels > 0) {
399 for (k = 1; k < nlabels; k++) {
400 LBL *L = &labels[k];
401 if (L->jumped > 0) {
402 _srecordf (lin, "// label %5d %5d in line %5d, goto\n", L->index, L->num, L->line);
403 } else if (L->nonexe) {
404 _srecordf (lin, "// label %5d %5d in line %5d, non-executable\n", L->index, L->num, L->line);
405 } else {
406 _srecordf (lin, "// label %5d %5d in line %5d\n", L->index, L->index, L->line);
407 }
408 code (nprocs, SYMBOLS, lin);
409 }
410 code (nprocs, SYMBOLS, "\n");
411 }
412 // Unclassified comments need a place.
413 int_4 xproc = nprocs;
414 int_4 lisn = curlin;
415 if (source[lisn].isn != 0) {
416 // If there is next module, delay comments after 'END' to the next module.
417 // We assume they belong there.
418 lisn--;
419 while (lisn >= 0 && source[lisn].isn == 0) {
420 source[lisn].proc = 0;
421 lisn--;
422 }
423 }
424 // Now assign comments to a module.
425 for (k = lisn; k >= 0; k--) {
426 FTN_LINE *flin = &source[k];
427 if (xproc > 1 && flin->proc > 0 && flin->proc < xproc) {
428 xproc = flin->proc;
429 }
430 if (flin->text != NULL && IS_COMMENT (flin->text[0]) && flin->proc == 0) {
431 flin->proc = xproc;
432 }
433 }
434 //
435 l_i = l_f = ERR;
436 for (k = 1; k < nftnlines && l_i == ERR; k++) {
437 FTN_LINE *flin = &source[k];
438 if (flin->proc == proc) {
439 l_i = k;
440 }
441 }
442 for (k = nftnlines - 1; k >= 1 && l_f == ERR; k--) {
443 FTN_LINE *flin = &source[k];
444 if (flin->proc == proc) {
445 l_f = k;
446 }
447 }
448 code (nprocs, LIST, newpage (modnam, "source-code"));
449 for (k = l_i; k <= l_f; k++) {
450 FTN_LINE *flin = &source[k];
451 RECORD lrec;
452 if (flin->isn > 0) {
453 if (flin->inc > 0) {
454 _srecordf (lrec, "// %1d%5d %6d %s\n", flin->inc, flin->num, flin->isn, flin->text);
455 } else {
456 _srecordf (lrec, "// %6d %6d %s\n", flin->num, flin->isn, flin->text);
457 }
458 } else {
459 if (flin->inc > 0) {
460 _srecordf (lrec, "// %1d%5d %s\n", flin->inc, flin->num, flin->text);
461 } else {
462 _srecordf (lrec, "// %6d %s\n", flin->num, flin->text);
463 }
464 }
465 code (nprocs, LIST, lrec);
466 }
467 }
468
© 2002-2024 J.M. van der Veer (jmvdveer@xs4all.nl)
|