1 /*
2 * Copyright (c) 1993-2019, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18 /** \file
19 \brief Compiler miscellaneous utility programs.
20 */
21
22 #include "miscutil.h"
23 #include "global.h"
24 #include "error.h"
25 #include "main.h"
26
27 #include <stdbool.h>
28 #include "flang/ArgParser/xflag.h"
29
30 /**
31 \brief Allocate space for and make new filename using mkperm.
32 */
33 char *
mkfname(char * oldname,char * oldsuf,char * newsuf)34 mkfname(char *oldname, char *oldsuf, char *newsuf)
35 {
36 char *p;
37
38 /* get enough space for oldname, newsuf, '.', '\0', and 1 extra: */
39 p = getitem(8, strlen(oldname) + strlen(newsuf) + 3);
40 strcpy(p, oldname);
41 return (mkperm(p, oldsuf, newsuf));
42 }
43
44 /** \brief Create literal string for STATIC STRING
45 *
46 * If isStringW is TRUE(1), oldstr is passed in as a wide string
47 * literal and a letter "L" needs to be prepended to the target string.
48 */
49 char *
literal_string(char * oldstr,int userlen,bool isStringW)50 literal_string(char *oldstr, int userlen, bool isStringW)
51 {
52 static char newstr[MAX_FILENAME_LEN];
53 char *from, *end, *curr, c;
54 int len, skip, start;
55
56 from = oldstr;
57 end = newstr + sizeof(newstr);
58 len = userlen - 1;
59
60 if (!isStringW) {
61 newstr[0] = '\"';
62 skip = 1;
63 start = 1;
64 } else {
65 newstr[0] = 'L';
66 newstr[1] = '\"';
67 skip = 4; /* wide char size */
68 start = 2;
69 }
70
71 for (curr = newstr + start; len-- && curr < end;) {
72 c = *from & 0xff;
73 from += skip;
74 if (c == '\"' || c == '\'' || c == '\\') {
75 *curr++ = '\\';
76 *curr++ = c;
77 } else if (c >= ' ' && c <= '~') {
78 *curr++ = c;
79 } else if (c == '\n') {
80 *curr++ = '\\';
81 *curr++ = 'n';
82 } else {
83 *curr++ = '\\';
84 snprintf(curr, newstr + MAX_FILENAME_LEN - curr, "%03o", c);
85 curr += 3;
86 }
87 }
88
89 *curr++ = '\"';
90 *curr = '\0';
91 return newstr;
92 }
93
94 bool
is_xflag_bit(int indx)95 is_xflag_bit(int indx)
96 {
97 return is_xflag_bitvector(indx);
98 }
99
100 /** \brief Called only from main() */
101 void
set_xflag(int indx,INT val)102 set_xflag(int indx, INT val)
103 {
104 set_xflag_value(flg.x, indx, val);
105 /* XXX Unexpected side effect: "set x flag" should not be upping opt level */
106 if (indx == 9 && flg.opt < 2) /* max cnt for unroller */
107 flg.opt = 2;
108 }
109
110 /** \brief Called only from main() */
111 void
set_yflag(int indx,INT val)112 set_yflag(int indx, INT val)
113 {
114 unset_xflag_value(flg.x, indx, val);
115 }
116
117 void
fprintf_str_esc_backslash(FILE * f,char * str)118 fprintf_str_esc_backslash(FILE *f, char *str)
119 {
120 int ch;
121 fputc('"', f);
122 while ((ch = *str++)) {
123 fputc(ch, f);
124 if (ch == '\\')
125 fputc('\\', f);
126 }
127 fputc('"', f);
128 }
129
130 /*
131 * error message
132 */
133 static void
invalid_size(const char * funcname,int dtsize,int size,const char * stgname)134 invalid_size(const char* funcname, int dtsize, int size, const char* stgname)
135 {
136 interrf(ERR_Fatal,
137 "%s: STG %s has invalid datatype size (%d) or structure size(%d)",
138 funcname, stgname, dtsize, size);
139 } /* invalid_size */
140
141 /*
142 * memory management
143 * allocate STG data structure, set the appropriate fields
144 * element zero is reserved, so stg_avail is initialized to 1
145 */
146 static void
stg_alloc_base(STG * stg,int dtsize,BIGUINT64 size,const char * name)147 stg_alloc_base(STG *stg, int dtsize, BIGUINT64 size, const char *name)
148 {
149 if (DBGBIT(7,0x10))
150 fprintf(gbl.dbgfil, "stg_alloc(stg=%p, dtsize=%d, size=%d, name=%s)\n",
151 stg, dtsize, size, name);
152 if (dtsize > 0 && size > 0) {
153 memset(stg, 0, sizeof(STG));
154 stg->stg_size = size;
155 stg->stg_dtsize = dtsize;
156 stg->stg_avail = 1;
157 stg->stg_cleared = 0;
158 stg->stg_name = name;
159 stg->stg_base = (void *)sccalloc(stg->stg_dtsize * size);
160 } else {
161 invalid_size("stg_alloc", dtsize, size, name);
162 }
163 } /* stg_alloc_base */
164
165 /*
166 * clear 'n' elements of the data structure starting at 'r'
167 * reset stg_cleared if we're initializing or extending the cleared region
168 */
169 void
stg_clear_force(STG * stg,BIGUINT64 r,BIGUINT64 n,bool force)170 stg_clear_force(STG *stg, BIGUINT64 r, BIGUINT64 n, bool force)
171 {
172 if (r >= 0 && n > 0) {
173 STG *thisstg;
174 if (r == stg->stg_cleared) {
175 stg->stg_cleared += n;
176 } else if (r == 0 && n > stg->stg_cleared) {
177 stg->stg_cleared = n;
178 }
179 for (thisstg = stg; thisstg; thisstg = (STG *)thisstg->stg_sidecar) {
180 thisstg->stg_cleared = stg->stg_cleared;
181 if (force || !STG_CHECKFLAG((*thisstg), STG_FLAG_NOCLEAR))
182 memset((char *)(thisstg->stg_base) + (r * thisstg->stg_dtsize), 0,
183 n * thisstg->stg_dtsize);
184 }
185 }
186 } /* stg_clear_force */
187
188 void
stg_clear(STG * stg,int r,int n)189 stg_clear(STG *stg, int r, int n)
190 {
191 if (r >= 0 && n > 0)
192 stg_clear_force(stg, r, n, false);
193 } /* stg_clear */
194
195 /*
196 * clear the data structure up to stg_avail
197 */
198 void
stg_clear_all(STG * stg)199 stg_clear_all(STG *stg)
200 {
201 stg_clear(stg, 0, stg->stg_avail);
202 } /* stg_clear_all */
203
204 /*
205 * allocate STG data structure, clear element zero
206 */
207 void
stg_alloc(STG * stg,int dtsize,int size,const char * name)208 stg_alloc(STG *stg, int dtsize, int size, const char *name)
209 {
210 stg_alloc_base(stg, dtsize, size, name);
211 stg_clear_force(stg, 0, 1, true);
212 } /* stg_alloc */
213
214 /*
215 * deallocate STG data structure
216 */
217 void
stg_delete(STG * stg)218 stg_delete(STG *stg)
219 {
220 if (DBGBIT(7,0x10))
221 fprintf(gbl.dbgfil, "stg_delete(stg=%p, dtsize=%d, size=%d, name=%s)\n",
222 stg, stg->stg_dtsize, stg->stg_size, stg->stg_name);
223 if (stg->stg_base)
224 sccfree((char *)stg->stg_base);
225 memset(stg, 0, sizeof(STG));
226 } /* stg_delete */
227
228 /*
229 * reset STG data structure
230 */
231 void
stg_reset(STG * stg)232 stg_reset(STG *stg)
233 {
234 STG *thisstg;
235 if (DBGBIT(7,0x10))
236 fprintf(gbl.dbgfil, "stg_reset(stg=%p, dtsize=%d, size=%d, name=%s)\n",
237 stg, stg->stg_dtsize, stg->stg_size, stg->stg_name);
238 for (thisstg = stg; thisstg; thisstg = (STG *)thisstg->stg_sidecar) {
239 thisstg->stg_avail = 1;
240 thisstg->stg_cleared = 0;
241 }
242 } /* stg_reset */
243
244 /*
245 * reallocate STG structure if we need the extra size (if stg_avail > stg_size)
246 * reallocate any sidecars as well
247 * the new size will be 2*(stg_avail-1), which must be >= 2*stg_size
248 */
249 void
stg_need(STG * stg)250 stg_need(STG *stg)
251 {
252 STG *thisstg;
253 /* if the compiler has recycled some previously allocated space,
254 * we need to reset the stg_cleared region */
255 if (stg->stg_cleared > stg->stg_avail)
256 stg->stg_cleared = stg->stg_avail;
257 if (stg->stg_avail > stg->stg_size) {
258 BIGUINT64 newsize, oldsize;
259 oldsize = stg->stg_size;
260 newsize = (stg->stg_avail - 1) * 2;
261 /* reallocate stg and all its sidecars */
262 for (thisstg = stg; thisstg; thisstg = (STG *)thisstg->stg_sidecar) {
263 if (DBGBIT(7,0x10))
264 fprintf(gbl.dbgfil, "stg_need(stg=%p, dtsize=%d, size=%d, newsize=%d, name=%s)\n",
265 thisstg, thisstg->stg_dtsize, thisstg->stg_size, newsize, thisstg->stg_name);
266 thisstg->stg_size = newsize;
267 thisstg->stg_base = (void *)sccrelal(
268 (char *)thisstg->stg_base, newsize * thisstg->stg_dtsize);
269 }
270 /* we have to clear all newly allocated elements, in case there
271 * are sidecars with the NOCLEAR flag set, so they get initially cleared */
272 stg_clear_force(stg, oldsize, newsize - oldsize, true);
273 }
274 if (stg->stg_avail > stg->stg_cleared) {
275 /* clear any new elements */
276 stg_clear_force(stg, stg->stg_cleared, stg->stg_avail - stg->stg_cleared, true);
277 }
278 } /* stg_need */
279
280 /*
281 * Allocate a sidecar, attach to list of sidecars
282 */
283 void
stg_alloc_sidecar(STG * basestg,STG * stg,int dtsize,const char * name)284 stg_alloc_sidecar(STG *basestg, STG *stg, int dtsize, const char *name)
285 {
286 if (DBGBIT(7,0x10))
287 fprintf(gbl.dbgfil, "stg_alloc_sidecar(basestg=%p, name=%s, stg=%p, dtsize=%d, name=%s)\n",
288 basestg, basestg->stg_name, stg, dtsize, name);
289 if (stg->stg_sidecar) {
290 interrf(ERR_Fatal, "%s: %s has a sidecar, may not add as sidecar to %s",
291 "stg_alloc_sidecar", stg->stg_name, basestg->stg_name);
292 }
293 stg_alloc_base(stg, dtsize, basestg->stg_size, name);
294 stg->stg_avail = basestg->stg_avail;
295 /* clear sidecar for any already-allocated elements */
296 stg_clear_force(stg, 0, stg->stg_size, true);
297 /* link this sidecar to the list of sidecars for the basestg */
298 stg->stg_sidecar = basestg->stg_sidecar;
299 basestg->stg_sidecar = (void *)stg;
300 } /* stg_alloc_sidecar */
301
302 /*
303 * error message
304 */
305 static void
sidecar_not_found(const char * funcname,STG * basestg,STG * stg)306 sidecar_not_found(const char *funcname, STG *basestg, STG *stg)
307 {
308 /* sidecar not found, this is an error */
309 interrf(ERR_Fatal, "%s: Sidecar %s to %s not found", funcname,
310 basestg->stg_name, stg->stg_name);
311 } /* sidecar_not_found */
312
313 /*
314 * Deallocate a sidecar, detach from list of sidecars
315 */
316 void
stg_delete_sidecar(STG * basestg,STG * stg)317 stg_delete_sidecar(STG *basestg, STG *stg)
318 {
319 if (DBGBIT(7,0x10))
320 fprintf(gbl.dbgfil, "stg_delete_sidecar(basestg=%p, name=%s, stg=%p, "
321 "dtsize=%d, name=%s)\n", basestg, basestg->stg_name, stg,
322 stg->stg_dtsize, stg->stg_name);
323 if ((STG *)basestg->stg_sidecar == stg) {
324 basestg->stg_sidecar = stg->stg_sidecar;
325 } else {
326 STG *sidecar;
327 for (sidecar = (STG *)basestg->stg_sidecar; sidecar;
328 sidecar = (STG *)sidecar->stg_sidecar) {
329 if ((STG *)sidecar->stg_sidecar == stg) {
330 sidecar->stg_sidecar = stg->stg_sidecar;
331 break;
332 }
333 }
334 if (!sidecar) {
335 sidecar_not_found("stg_delete_sidecar", basestg, stg);
336 }
337 }
338 stg_delete(stg);
339 } /* stg_delete_sidecar */
340
341 /*
342 * reserve next n elements at stg_avail; increment stg_avail;
343 * grow, if necessary;
344 * clear newly allocated elements; return the first such element.
345 */
346 int
stg_next(STG * stg,int n)347 stg_next(STG *stg, int n)
348 {
349 STG *thisstg;
350 unsigned int r = stg->stg_avail;
351 if (n == 0)
352 return 0;
353 if (n < 0) {
354 interrf(ERR_Fatal, "stg_next(%s,%d) called with n < 0", stg->stg_name, n);
355 return 0;
356 }
357 /* if the compiler has recycled some previously allocated space,
358 * we need to reset the stg_cleared region */
359 if (stg->stg_cleared > r)
360 stg->stg_cleared = r;
361 stg->stg_avail += n;
362 for (thisstg = (STG *)stg->stg_sidecar; thisstg;
363 thisstg = (STG *)thisstg->stg_sidecar) {
364 thisstg->stg_avail = stg->stg_avail;
365 thisstg->stg_cleared = stg->stg_cleared;
366 }
367 if (stg->stg_avail > stg->stg_size) {
368 stg_need(stg);
369 } else {
370 stg_clear(stg, stg->stg_cleared, stg->stg_avail - stg->stg_cleared);
371 }
372 return r;
373 } /* stg_next */
374
375 /*
376 * error message
377 */
378 static void
too_small_for_freelist(const char * funcname,STG * stg)379 too_small_for_freelist(const char *funcname, STG *stg)
380 {
381 interrf(ERR_Fatal, "%s: structure %s too small for a freelist link, size=%d",
382 funcname, stg->stg_name, stg->stg_dtsize);
383 } /* too_small_for_freelist */
384
385 static char*
freefield(STG * stg,BIGUINT64 r)386 freefield(STG* stg, BIGUINT64 r)
387 {
388 char *base;
389 /* get stg_base */
390 base = (char *)stg->stg_base;
391 /* add the offset of the r'th element (r*dtsize) */
392 base += r * stg->stg_dtsize;
393 /* add freelink offset */
394 base += stg->stg_freelink_offset;
395 return base;
396 } /* freefield */
397
398 /*
399 * get next element from the free list, if it's not null.
400 * reset the free list from the free list link.
401 * otherwise, just get the next available element from stg_avail
402 * the link to the next free element is stored at 'word 0' of the structure
403 */
404 int
stg_next_freelist(STG * stg)405 stg_next_freelist(STG *stg)
406 {
407 int r = stg->stg_free;
408 if (!r) {
409 r = stg_next(stg, 1);
410 stg_clear(stg, r, 1);
411 } else {
412 char *base;
413 if (stg->stg_dtsize < sizeof(int))
414 too_small_for_freelist("stg_next_freelist", stg);
415 /* get freelink for entry 'r' */
416 base = freefield(stg, r);
417 /* move stg_free to the next free element */
418 stg->stg_free = *(int *)base;
419 /* clear the new element */
420 stg_clear(stg, r, 1);
421 }
422 return r;
423 } /* stg_next_freelist */
424
425 /*
426 * return latest entry (from stg_next)
427 */
428 void
stg_return(STG * stg)429 stg_return(STG *stg)
430 {
431 STG *thisstg;
432 unsigned int r = stg->stg_avail - 1;
433 stg->stg_avail = r;
434 if (stg->stg_cleared > r)
435 stg->stg_cleared = r;
436 for (thisstg = (STG *)stg->stg_sidecar; thisstg;
437 thisstg = (STG *)thisstg->stg_sidecar) {
438 thisstg->stg_avail = stg->stg_avail;
439 thisstg->stg_cleared = stg->stg_cleared;
440 }
441 } /* stg_return */
442
443 /*
444 * add element to the free list
445 * store the link to the next free element at 'word 0'
446 */
447 void
stg_add_freelist(STG * stg,int r)448 stg_add_freelist(STG *stg, int r)
449 {
450 char *base;
451 if (stg->stg_dtsize < sizeof(int))
452 too_small_for_freelist("stg_next_freelist", stg);
453 /* clear the recycled element */
454 stg_clear(stg, r, 1);
455 /* get stg_base */
456 base = freefield(stg, r);
457 /* link to the free list */
458 *(int *)base = stg->stg_free;
459 stg->stg_free = r;
460 } /* stg_add_freelist */
461
462 /*
463 * set the free list link field offset
464 */
465 void
stg_set_freelink(STG * stg,int offset)466 stg_set_freelink(STG* stg, int offset)
467 {
468 stg->stg_freelink_offset = offset;
469 } /* stg_set_freelink */
470
471