1 /*
2  * Copyright (c) 2015-2018, 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 /**
19    \file llassem_common.c
20    Some various functions that emit LLVM IR.
21  */
22 
23 #include "llassem_common.h"
24 #include "dinit.h"
25 #include "dinitutl.h"
26 #include "version.h"
27 #include "machreg.h"
28 #include "assem.h"
29 #include "x86.h"
30 #include "llutil.h"
31 #include "cgllvm.h"
32 #include "cgmain.h"
33 #include "cg.h"
34 #include "llassem.h"
35 
36 union {
37   unsigned short i8;
38   unsigned char byte[2];
39 } i8bit;
40 
41 union {
42   unsigned short i16;
43   unsigned char byte[2];
44 } i16bit;
45 
46 union {
47   unsigned int i32;
48   float r4;
49   unsigned char byte[4];
50 } i32bit;
51 
52 union {
53   unsigned long i64; /* need to make sure this is 64 bit */
54   double r8;
55   unsigned char byte[8];
56 } i64bit;
57 
58 #include "dtypeutl.h"
59 
60 AGB_t agb;
61 
62 DSRT *lcl_inits;
63 DSRT *section_inits;
64 DSRT *extern_inits;
65 char static_name[MXIDLN];
66 int first_data;
67 int ag_cmblks;
68 int ag_procs;
69 int ag_other;
70 int ag_global;
71 int ag_typedef;
72 int ag_static;
73 int ag_intrin;
74 int ag_local;
75 int ag_funcptr;
76 
77 static void put_ncharstring_n(char *, ISZ_T, int);
78 static void put_zeroes(ISZ_T);
79 static void put_cmplx_n(int, int);
80 static void put_dcmplx_n(int, int);
81 static void put_i8(int);
82 static void put_i16(int);
83 static void put_r4(INT);
84 static void put_r8(int, int);
85 static void put_int(INT);
86 static void put_int8(INT);
87 static void put_float(INT);
88 static void put_double(int);
89 static void put_cmplx_n(int, int);
90 static void put_float_cmplx(int, int);
91 static void put_double_cmplx(int, int);
92 static void put_string(char *, int);
93 static void put_zeroes_bysize(ISZ_T, int);
94 static void add_ctor(char *);
95 
96 static void
add_ctor(char * constructor)97 add_ctor(char *constructor)
98 {
99   LL_Type *ret = ll_create_basic_type(cpu_llvm_module, LL_VOID, 0);
100   LL_Function *fn;
101   char buff[128];
102   snprintf(buff, sizeof(buff), "declare void @%s()", constructor);
103   fn = ll_create_function(cpu_llvm_module, buff + 13, ret, 0, 0, 0, "",
104                           LL_NO_LINKAGE);
105   llvm_ctor_add(constructor);
106   ll_proto_add(fn->name, NULL);
107   ll_proto_set_intrinsic(fn->name, buff);
108 }
109 
110 char *
put_next_member(char * ptr)111 put_next_member(char *ptr)
112 {
113   if (!ptr)
114     return NULL;
115   if (*ptr == ',')
116     ptr++;
117   while (*ptr != ',' && *ptr != '\0') {
118     fprintf(ASMFIL, "%c", *ptr);
119     ptr++;
120   }
121   fprintf(ASMFIL, " ");
122   return ptr;
123 }
124 
125 ISZ_T
put_skip(ISZ_T old,ISZ_T New)126 put_skip(ISZ_T old, ISZ_T New)
127 {
128   ISZ_T amt;
129 
130   if ((amt = New - old) > 0) {
131     INT i;
132     i = amt;
133     while (i > 32) {
134       fprintf(ASMFIL, "i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 "
135                       "0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 "
136                       "0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0");
137       i -= 32;
138       if (i)
139         fprintf(ASMFIL, ",");
140     }
141     if (i) {
142       while (1) {
143         fprintf(ASMFIL, "i8 0");
144         i--;
145         if (i == 0)
146           break;
147         fprintf(ASMFIL, ",");
148       }
149     }
150   } else {
151     assert(amt == 0, "assem.c-put_skip old,new not in sync", New, ERR_Severe);
152   }
153   return amt;
154 }
155 
156 void
emit_init(DTYPE tdtype,ISZ_T tconval,ISZ_T * addr,ISZ_T * repeat_cnt,ISZ_T loc_base,ISZ_T * i8cnt,int * ptrcnt,char ** cptr)157 emit_init(DTYPE tdtype, ISZ_T tconval, ISZ_T *addr, ISZ_T *repeat_cnt,
158           ISZ_T loc_base, ISZ_T *i8cnt, int *ptrcnt, char **cptr)
159 {
160   ISZ_T al;
161   int area, d;
162   int size_of_item;
163   int putval;
164   INT skip_size;
165   char str[32];
166   char *initstr = NULL;
167   DINIT_REC *item;
168   area = LLVM_LONGTERM_AREA;
169   const ISZ_T orig_tconval = tconval;
170 
171   switch ((int)tdtype) {
172   case 0: /* alignment record */
173           /*  word or halfword alignment required: */
174 #if DEBUG
175     assert(tconval == 7 || tconval == 3 || tconval == 1 || tconval == 0,
176            "emit_init:bad align", (int)tconval, ERR_Severe);
177 #endif
178     skip_size = ALIGN(*addr, tconval) - *addr;
179     if (skip_size == 0) {
180       *addr = ALIGN(*addr, tconval);
181       break;
182     }
183     if (DBGBIT(5, 32)) {
184       fprintf(gbl.dbgfil, "emit_init:0 first_data:%d i8cnt:%ld ptrcnt:%d\n",
185               first_data, *i8cnt, *ptrcnt);
186     }
187     if (*ptrcnt) {
188       if (!first_data)
189         fprintf(ASMFIL, ", ");
190       *cptr = put_next_member(*cptr);
191       fprintf(ASMFIL, "[" /*]*/);
192       *ptrcnt = 0;
193     } else if (!(*i8cnt)) {
194       if (!first_data)
195         fprintf(ASMFIL, ", ");
196       *cptr = put_next_member(*cptr);
197       fprintf(ASMFIL, "[" /*]*/);
198     } else if (*i8cnt) {
199       if (!first_data)
200         fprintf(ASMFIL, ", ");
201     }
202     *i8cnt = *i8cnt + put_skip(*addr, ALIGN(*addr, tconval));
203     *addr = ALIGN(*addr, tconval);
204     first_data = 0;
205     break;
206   case DINIT_ZEROES:
207     if (!tconval) {
208       *addr += tconval;
209       break;
210     }
211     if (DBGBIT(5, 32)) {
212       fprintf(gbl.dbgfil,
213               "emit_init:DINIT_ZEROES first_data:%d i8cnt:%ld ptrcnt:%d\n",
214               first_data, *i8cnt, *ptrcnt);
215     }
216     if (*ptrcnt) {
217       if (!first_data)
218         fprintf(ASMFIL, ", ");
219       *cptr = put_next_member(*cptr);
220       fprintf(ASMFIL, "[" /*]*/);
221       *ptrcnt = 0;
222     } else if (!(*i8cnt)) {
223       if (!first_data)
224         fprintf(ASMFIL, ", ");
225       *cptr = put_next_member(*cptr);
226       fprintf(ASMFIL, "[" /*]*/);
227     } else if (*i8cnt) {
228       if (!first_data)
229         fprintf(ASMFIL, ", ");
230     }
231     put_zeroes((int)tconval);
232     *i8cnt = *i8cnt + ((int)tconval);
233     *addr += tconval;
234     first_data = 0;
235     break;
236   case DINIT_LABEL:
237     /*  word to be init'ed with address of label 'tconval' */
238     al = alignment(DT_CPTR);
239     skip_size = ALIGN(*addr, al) - *addr;
240     if (DBGBIT(5, 32)) {
241       fprintf(gbl.dbgfil,
242               "emit_init:DINIT_LABEL first_data:%d i8cnt:%ld ptrcnt:%d\n",
243               first_data, *i8cnt, *ptrcnt);
244     }
245 
246     if (skip_size) { /* if *i8cnt - just add to the end */
247       if (!first_data)
248         fprintf(ASMFIL, ", ");
249       if (*i8cnt) {
250         *i8cnt = put_skip(*addr, ALIGN(*addr, al));
251         *i8cnt = 0;
252         fprintf(ASMFIL, /*[*/ "], ");
253       } else if (*ptrcnt || !(*i8cnt)) {
254 #ifdef OMP_OFFLOAD_LLVM
255         // TODO ompaccel. Hackery for TGT structs. It must be fixed later.
256         if (flg.omptarget)
257           fprintf(ASMFIL, " i8* ");
258         else
259 #endif
260           *cptr = put_next_member(*cptr);
261         fprintf(ASMFIL, "[" /*]*/);
262         *i8cnt = put_skip(*addr, ALIGN(*addr, al));
263         fprintf(ASMFIL, /*[*/ "], ");
264       }
265     } else if (*i8cnt) {
266       fprintf(ASMFIL, /*[*/ "], ");
267       *i8cnt = 0;
268     } else if (!first_data)
269       fprintf(ASMFIL, ", ");
270 #ifdef OMP_OFFLOAD_LLVM
271     // TODO ompaccel. Hackery for TGT structs. It must be fixed later.
272     if (flg.omptarget)
273       fprintf(ASMFIL, " i8* ");
274     else
275 #endif
276       *cptr = put_next_member(*cptr);
277     *addr = ALIGN(*addr, al);
278     if (DBGBIT(5, 32)) {
279       fprintf(gbl.dbgfil,
280               "emit_init:DINIT_LABEL calling put_addr "
281               "first_data:%d i8cnt:%ld ptrcnt:%d\n",
282               first_data, *i8cnt, *ptrcnt);
283     }
284     put_addr((SPTR)tconval, 0, DT_NONE); // ???
285     (*ptrcnt)++;
286     *addr += size_of(DT_CPTR);
287     first_data = 0;
288     break;
289 #ifdef DINIT_FUNCCOUNT
290   case DINIT_FUNCCOUNT:
291     gbl.func_count = tconval;
292     break;
293 #endif
294   case DINIT_OFFSET:
295     skip_size = (tconval + loc_base) - *addr;
296     if (skip_size == 0) {
297       *addr = tconval + loc_base;
298       break;
299     }
300     if (DBGBIT(5, 32)) {
301       fprintf(gbl.dbgfil,
302               "emit_init:DINIT_OFFSET first_data:%d i8cnt:%ld ptrcnt:%d\n",
303               first_data, *i8cnt, *ptrcnt);
304     }
305     if (*ptrcnt) {
306       if (!first_data)
307         fprintf(ASMFIL, ", ");
308       *cptr = put_next_member(*cptr);
309       fprintf(ASMFIL, "[" /*]*/);
310       *ptrcnt = 0;
311     } else if (!(*i8cnt)) {
312       if (!first_data)
313         fprintf(ASMFIL, ", ");
314       *cptr = put_next_member(*cptr);
315       fprintf(ASMFIL, "[" /*]*/);
316     } else if (*i8cnt) {
317       if (!first_data)
318         fprintf(ASMFIL, ", ");
319     }
320     *i8cnt = *i8cnt + put_skip(*addr, tconval + loc_base);
321     *addr = tconval + loc_base;
322     first_data = 0;
323     break;
324   case DINIT_REPEAT:
325     *repeat_cnt = tconval;
326     break;
327   case DINIT_SECT:
328     break;
329   case DINIT_DATASECT:
330     break;
331   case DINIT_STRING:
332     /* read the string from the dinit file until the length is exhausted */
333     *addr += tconval;
334     if (tconval == 0) {
335       break;
336     }
337     if (DBGBIT(5, 32)) {
338       fprintf(gbl.dbgfil,
339               "emit_init:DINIT_STRING first_data:%d i8cnt:%ld ptrcnt:%d\n",
340               first_data, *i8cnt, *ptrcnt);
341     }
342     if (*ptrcnt) {
343       if (!first_data)
344         fprintf(ASMFIL, ", ");
345       *cptr = put_next_member(*cptr);
346       fprintf(ASMFIL, "[" /*]*/);
347       *ptrcnt = 0;
348     } else if (!(*i8cnt)) {
349       if (!first_data)
350         fprintf(ASMFIL, ", ");
351       *cptr = put_next_member(*cptr);
352       fprintf(ASMFIL, "[" /*]*/);
353     } else if (*i8cnt) {
354       if (!first_data)
355         fprintf(ASMFIL, ", ");
356     }
357 
358     /* Output the data */
359     *i8cnt += tconval;
360     while (tconval > 0) {
361       if (tconval != orig_tconval)
362         fprintf(ASMFIL, ", ");
363       if (tconval > 32) {
364         dinit_read_string(32, str);
365         put_string_n(str, 32, 0);
366         tconval -= 32;
367       } else {
368         dinit_read_string(tconval, str);
369         put_string_n(str, tconval, 0);
370         tconval = 0;
371       }
372     }
373 
374     /* We have printed out an entire string, close it */
375     first_data = 0;
376     break;
377   default:
378     assert(tdtype > 0, "emit_init:bad dinit rec", tdtype, ERR_Severe);
379     size_of_item = size_of(tdtype);
380 
381     if (*repeat_cnt > 1) {
382       /* TO DO: We may be able to optimize this with zeroinitializer
383        * if all i8 before and after this are all zero.
384        *
385        */
386       switch (DTY(tdtype)) {
387       case TY_INT8:
388       case TY_LOG8:
389         if (CONVAL2G(tconval) == 0 &&
390             (!XBIT(124, 0x400) || CONVAL1G(tconval) == 0))
391           goto do_zeroes;
392         break;
393       case TY_INT:
394       case TY_LOG:
395       case TY_SINT:
396       case TY_SLOG:
397       case TY_BINT:
398       case TY_BLOG:
399       case TY_FLOAT:
400         if (tconval == 0)
401           goto do_zeroes;
402         break;
403       case TY_DBLE:
404         if (tconval == stb.dbl0)
405           goto do_zeroes;
406         break;
407       case TY_CMPLX:
408         if (CONVAL1G(tconval) == 0 && CONVAL2G(tconval) == 0)
409           goto do_zeroes;
410         break;
411       case TY_DCMPLX:
412         if (CONVAL1G(tconval) == stb.dbl0 && CONVAL2G(tconval) == stb.dbl0)
413           goto do_zeroes;
414         break;
415 #ifdef LONG_DOUBLE_FLOAT128
416       case TY_FLOAT128:
417         if (tconval == stb.float128_0)
418           goto do_zeroes;
419         break;
420       case TY_CMPLX128:
421         if (CONVAL1G(tconval) == stb.float128_0 &&
422             CONVAL2G(tconval) == stb.float128_0)
423           goto do_zeroes;
424         break;
425 #endif /* LONG_DOUBLE_FLOAT128 */
426       default:
427         break;
428       }
429     }
430     /* emit data value, loop if repeat count present */
431     putval = 1;
432     if (size_of_item == 0) {
433       putval = 0;
434       *repeat_cnt = 1;
435       break;
436     }
437     do {
438       if (DTY(tdtype) != TY_PTR && DTY(tdtype) != TY_STRUCT) {
439         if (*ptrcnt) {
440           if (!first_data)
441             fprintf(ASMFIL, ", ");
442           *cptr = put_next_member(*cptr);
443           fprintf(ASMFIL, " [" /*]*/);
444           *ptrcnt = 0;
445         } else if (!(*i8cnt)) {
446           if (!first_data)
447             fprintf(ASMFIL, ", ");
448           *cptr = put_next_member(*cptr);
449           fprintf(ASMFIL, " [" /*]*/);
450         } else if (*i8cnt) {
451           if (!first_data)
452             fprintf(ASMFIL, ", ");
453         }
454       }
455       switch (DTY(tdtype)) {
456       case TY_INT8:
457       case TY_LOG8:
458       case TY_DWORD:
459         if (DBGBIT(5, 32)) {
460           fprintf(gbl.dbgfil,
461                   "emit_init:put_i32 first_data:%d i8cnt:%ld ptrcnt:%d\n",
462                   first_data, *i8cnt, *ptrcnt);
463         }
464         put_i32(CONVAL2G(tconval));
465         fprintf(ASMFIL, ", ");
466         if (DBGBIT(5, 32)) {
467           fprintf(gbl.dbgfil,
468                   "emit_init:put_i32 first_data:%d i8cnt:%ld ptrcnt:%d\n",
469                   first_data, *i8cnt, *ptrcnt);
470         }
471         if (XBIT(124, 0x400)) {
472           put_i32(CONVAL1G(tconval));
473         } else {
474           put_i32(0);
475         }
476         break;
477 
478       case TY_INT:
479       case TY_LOG:
480       case TY_WORD:
481         if (DBGBIT(5, 32)) {
482           fprintf(gbl.dbgfil,
483                   "emit_init:put_i32 first_data:%d i8cnt:%ld ptrcnt:%d\n",
484                   first_data, *i8cnt, *ptrcnt);
485         }
486         put_i32(tconval);
487         break;
488       case TY_SINT:
489       case TY_SLOG:
490         if (DBGBIT(5, 32)) {
491           fprintf(gbl.dbgfil,
492                   "emit_init:put_i16 first_data:%d i8cnt:%ld ptrcnt:%d\n",
493                   first_data, *i8cnt, *ptrcnt);
494         }
495         put_i16((int)tconval);
496         break;
497 
498       case TY_BINT:
499       case TY_BLOG:
500         if (DBGBIT(5, 32)) {
501           fprintf(gbl.dbgfil,
502                   "emit_init:put_i8 first_data:%d i8cnt:%ld ptrcnt:%d\n",
503                   first_data, *i8cnt, *ptrcnt);
504         }
505         put_i8((int)tconval);
506         break;
507 
508       case TY_FLOAT:
509         if (DBGBIT(5, 32)) {
510           fprintf(gbl.dbgfil,
511                   "emit_init:put_r4 first_data:%d i8cnt:%ld ptrcnt:%d\n",
512                   first_data, *i8cnt, *ptrcnt);
513         }
514         put_r4(tconval);
515         break;
516 
517       case TY_DBLE:
518         if (DBGBIT(5, 32)) {
519           fprintf(gbl.dbgfil,
520                   "emit_init:put_r8 first_data:%d i8cnt:%ld ptrcnt:%d\n",
521                   first_data, *i8cnt, *ptrcnt);
522         }
523         put_r8((int)tconval, putval);
524         break;
525 
526       case TY_CMPLX:
527         if (DBGBIT(5, 32)) {
528           fprintf(gbl.dbgfil,
529                   "emit_init:put_cmplx_n first_data:%d i8cnt:%ld ptrcnt:%d\n",
530                   first_data, *i8cnt, *ptrcnt);
531         }
532         put_cmplx_n((int)tconval, putval);
533         break;
534 
535       case TY_DCMPLX:
536         if (DBGBIT(5, 32)) {
537           fprintf(gbl.dbgfil,
538                   "emit_init:put_dcmplx_n first_data:%d i8cnt:%ld ptrcnt:%d\n",
539                   first_data, *i8cnt, *ptrcnt);
540         }
541         put_dcmplx_n((int)tconval, putval);
542         break;
543 
544       case TY_PTR:
545         if (*i8cnt) {
546           fprintf(ASMFIL, /*[*/ "], ");
547         } else if (!first_data)
548           fprintf(ASMFIL, ", ");
549         *ptrcnt = *ptrcnt + 1;
550         *i8cnt = 0;
551         *cptr = put_next_member(*cptr);
552 
553         if (DBGBIT(5, 32)) {
554           fprintf(gbl.dbgfil,
555                   "emit_init:put_addr first_data:%d i8cnt:%ld ptrcnt:%d\n",
556                   first_data, *i8cnt, *ptrcnt);
557         }
558         if (STYPEG(tconval) != ST_CONST) {
559           put_addr(SPTR_NULL, tconval, DT_NONE);
560         } else {
561           put_addr(SymConval1((SPTR)tconval), CONVAL2G(tconval),
562                    DT_NONE); // ???
563         }
564         break;
565 
566       case TY_CHAR:
567         size_of_item = DTY(DTYPEG(tconval) + 1);
568         if (DBGBIT(5, 32)) {
569           fprintf(gbl.dbgfil,
570                   "emit_init:put_str_n first_data:%d i8cnt:%ld ptrcnt:%d\n",
571                   first_data, *i8cnt, *ptrcnt);
572         }
573         put_string_n(stb.n_base + CONVAL1G((int)tconval),
574                      DTY(DTYPEG((int)tconval) + 1), 0);
575         break;
576 
577       case TY_NCHAR:
578         /* need to write nchar in 2 bytes because we make everything as i8 */
579         put_ncharstring_n(stb.n_base + CONVAL1G((int)tconval),
580                           DTY(DTYPEG((int)tconval) + 1), 16);
581         break;
582 
583       case TY_STRUCT:
584         if (is_empty_typedef(tdtype)) {
585           break;
586         }
587 
588 #ifdef LONG_DOUBLE_FLOAT128
589       case TY_X87:
590         put_r8(CONVAL1G(tconval), putval);
591         fputc(',', ASMFIL);
592         put_r8(CONVAL2G(tconval), putval);
593         fputc(',', ASMFIL);
594         put_r8(CONVAL3G(tconval), putval);
595         fputc(',', ASMFIL);
596         put_r8(0, putval);
597         put_r8(CONVAL4G(tconval), putval);
598         fputc(',', ASMFIL);
599         break;
600       case TY_X87CMPLX:
601         put_r8(CONVAL1G(CONVAL1G(tconval)), putval);
602         fputc(',', ASMFIL);
603         put_r8(CONVAL2G(CONVAL1G(tconval)), putval);
604         fputc(',', ASMFIL);
605         put_r8(CONVAL3G(CONVAL1G(tconval)), putval);
606         fputc(',', ASMFIL);
607         put_r8(CONVAL4G(CONVAL1G(tconval)), putval);
608         fputc(',', ASMFIL);
609         put_r8(0, putval);
610         put_r8(CONVAL1G(CONVAL2G(tconval)), putval);
611         fputc(',', ASMFIL);
612         put_r8(CONVAL2G(CONVAL2G(tconval)), putval);
613         fputc(',', ASMFIL);
614         put_r8(CONVAL3G(CONVAL2G(tconval)), putval);
615         fputc(',', ASMFIL);
616         put_r8(CONVAL4G(CONVAL2G(tconval)), putval);
617         fputc(',', ASMFIL);
618         put_r8(0, putval);
619         break;
620 #endif /* LONG_DOUBLE_FLOAT128 */
621 
622       default:
623         interr("emit_init:bad dt", tdtype, ERR_Severe);
624       }
625       *addr += size_of_item;
626       if (DTY(tdtype) != TY_PTR)
627         *i8cnt = *i8cnt + size_of_item;
628       putval = 0;
629       first_data = 0;
630 
631     } while (--(*repeat_cnt));
632     *repeat_cnt = 1;
633     break;
634   do_zeroes:
635     if (*ptrcnt) {
636       if (!first_data)
637         fprintf(ASMFIL, ", ");
638       *cptr = put_next_member(*cptr);
639       fprintf(ASMFIL, " [" /*]*/);
640       *ptrcnt = 0;
641     } else if (!(*i8cnt)) {
642       if (!first_data)
643         fprintf(ASMFIL, ", ");
644       *cptr = put_next_member(*cptr);
645       fprintf(ASMFIL, " [" /*]*/);
646     } else if (*i8cnt) {
647       if (!first_data)
648         fprintf(ASMFIL, ", ");
649     }
650     if (DBGBIT(5, 32)) {
651       fprintf(gbl.dbgfil,
652               "emit_init:put_zeroes at end first_data:%d i8cnt:%ld ptrcnt:%d\n",
653               first_data, *i8cnt, *ptrcnt);
654     }
655     put_zeroes((*repeat_cnt) * size_of_item);
656     *i8cnt = *i8cnt + (*repeat_cnt) * size_of_item;
657     *addr += (*repeat_cnt) * size_of_item;
658     *repeat_cnt = 1;
659     first_data = 0;
660     break;
661   }
662 }
663 
664 void
put_string_n(char * p,ISZ_T len,int size)665 put_string_n(char *p, ISZ_T len, int size)
666 {
667   int n;
668   char ch;
669   char *ptrch = "i8";
670   char chnm[10];
671 
672   /* check for wide string - size is given by caller */
673   if (size) {
674     snprintf(chnm, sizeof(chnm), "i%d", size);
675     ptrch = chnm;
676   }
677 
678   if (len == 0) {
679     fprintf(ASMFIL, "%s 0", ptrch);
680     return;
681   }
682   n = 0;
683   while (len--) {
684     ch = *p;
685     fprintf(ASMFIL, "%s %u", ptrch, ch & 0xff);
686     if (len)
687       fprintf(ASMFIL, ",");
688     ++p;
689     ++n;
690   }
691 } /* put_string_n */
692 
693 static void
put_ncharstring_n(char * p,ISZ_T len,int size_of_char)694 put_ncharstring_n(char *p, ISZ_T len, int size_of_char)
695 {
696   int n, bytes;
697   char ch;
698   char *ptrch = "i8";
699   char chnm[10];
700   union {
701     char a[2];
702     short i;
703   } chtmp;
704 
705   if (len == 0) {
706     fprintf(ASMFIL, "%s 0,", ptrch);
707     fprintf(ASMFIL, "%s 0", ptrch);
708     return;
709   }
710   n = 0;
711 
712   while (len > 0) {
713     int val = kanji_char((unsigned char *)p, len, &bytes);
714     p += bytes;
715     len -= bytes;
716     chtmp.i = val;
717     fprintf(ASMFIL, "%s %u, ", ptrch, chtmp.a[0] & 0xff);
718     fprintf(ASMFIL, "%s %u", ptrch, chtmp.a[1] & 0xff);
719     if (len)
720       fprintf(ASMFIL, ",");
721   }
722 
723 } /* put_string_n */
724 
725 static void
put_zeroes(ISZ_T len)726 put_zeroes(ISZ_T len)
727 {
728   ISZ_T i;
729   i = len;
730   while (i > 32) {
731     fprintf(ASMFIL, "i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 "
732                     "0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 "
733                     "0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0,i8 0");
734     i -= 32;
735     if (i)
736       fprintf(ASMFIL, ",");
737   }
738   if (i) {
739     while (1) {
740       fprintf(ASMFIL, "i8 0");
741       i--;
742       if (i == 0)
743         break;
744       fprintf(ASMFIL, ",");
745     }
746   }
747 }
748 
749 static void
put_zeroes_bytype(ISZ_T len,char * ttype,char * initval)750 put_zeroes_bytype(ISZ_T len, char *ttype, char *initval)
751 {
752   ISZ_T i;
753   i = len;
754   if (i) {
755     while (1) {
756       fprintf(ASMFIL, "%s %s", ttype, initval);
757       i--;
758       if (i == 0)
759         break;
760       fprintf(ASMFIL, ",");
761     }
762   }
763 }
764 
765 static void
put_i8(int val)766 put_i8(int val)
767 {
768   int i;
769   i8bit.i8 = (short)val;
770   fprintf(ASMFIL, "i8 %u", i8bit.byte[0] & 0xff);
771 }
772 
773 /* write:  i8 x1, i8 x2 */
774 static void
put_i16(int val)775 put_i16(int val)
776 {
777   int i;
778   i16bit.i16 = val;
779   for (i = 0; i < 2; i++) {
780     fprintf(ASMFIL, "i8 %u", i16bit.byte[i] & 0xff);
781     if (i < 1)
782       fprintf(ASMFIL, ",");
783   }
784 }
785 
786 /* write:  i8 0x?, i8 0x?, i8 0x?, i8 0x? */
787 void
put_i32(int val)788 put_i32(int val)
789 {
790   int i;
791   i32bit.i32 = val;
792   for (i = 0; i < 4; i++) {
793     fprintf(ASMFIL, "i8 %u", i32bit.byte[i] & 0xff);
794     if (i < 3)
795       fprintf(ASMFIL, ", ");
796   }
797 }
798 
799 void
put_short(int val)800 put_short(int val)
801 {
802   fprintf(ASMFIL, "i16 %u", val);
803 }
804 
805 static void
put_int(INT val)806 put_int(INT val)
807 {
808   fprintf(ASMFIL, "i%d %u", DIR_LONG_SIZE, val);
809 }
810 
811 void
put_int4(int val)812 put_int4(int val)
813 {
814   fprintf(ASMFIL, "i32 %u", val);
815 }
816 
817 static void
put_int8(INT val)818 put_int8(INT val)
819 {
820   fprintf(ASMFIL, "i64 %lu", (unsigned long)val);
821 }
822 
823 /* write:  i8 0x?, i8 0x?, i8 0x?, i8 0x? */
824 static void
put_r4(INT val)825 put_r4(INT val)
826 {
827   int i;
828   i32bit.i32 = val;
829   for (i = 0; i < 4; i++) {
830     fprintf(ASMFIL, "i8 %u", i32bit.byte[i] & 0xff);
831     if (i < 3)
832       fprintf(ASMFIL, ",");
833   }
834 }
835 
836 static void
put_float(INT val)837 put_float(INT val)
838 {
839   union xx_u xx;
840   union {
841     double d;
842     INT tmp[2];
843   } dtmp, dtmp2;
844   xx.ww = val;
845   fprintf(ASMFIL, "float ");
846   xdble(xx.ww, dtmp2.tmp);
847   xdtomd(dtmp2.tmp, &dtmp.d);
848 
849   if (dtmp.tmp[0] == -1) /* pick up the quiet nan */
850     fprintf(ASMFIL, "0x7FF80000");
851   else if (!dtmp.tmp[1])
852     fprintf(ASMFIL, "0x00000000");
853   else
854     fprintf(ASMFIL, "0x%X", dtmp.tmp[1]);
855 
856   if (!dtmp.tmp[0] || dtmp.tmp[0] == -1)
857     fprintf(ASMFIL, "00000000");
858   else
859     fprintf(ASMFIL, "%X", dtmp.tmp[0]);
860 }
861 
862 static void
put_double(int sptr)863 put_double(int sptr)
864 {
865   INT num[2];
866   num[0] = CONVAL1G(sptr);
867   num[1] = CONVAL2G(sptr);
868   fprintf(ASMFIL, "double ");
869 
870   if ((num[0] & 0x7ff00000) == 0x7ff00000) /* exponent == 2047 */
871     fprintf(ASMFIL, "0x%08x00000000", num[0]);
872   else {
873     fprintf(ASMFIL, "0x%.8X%.8X", num[0], num[1]);
874   }
875 }
876 
877 static void
put_r8(int sptr,int putval)878 put_r8(int sptr, int putval)
879 {
880   INT num[2];
881 
882   num[0] = CONVAL1G(sptr);
883   num[1] = CONVAL2G(sptr);
884   if (flg.endian) {
885     put_r4(num[0]);
886     fprintf(ASMFIL, ",");
887     put_r4(num[1]);
888   } else {
889     put_r4(num[1]);
890     fprintf(ASMFIL, ",");
891     put_r4(num[0]);
892   }
893 }
894 
895 static void
put_cmplx_n(int sptr,int putval)896 put_cmplx_n(int sptr, int putval)
897 {
898   put_r4(CONVAL1G(sptr));
899   fprintf(ASMFIL, ",");
900   put_r4(CONVAL2G(sptr));
901 }
902 
903 static void
put_float_cmplx(int sptr,int putval)904 put_float_cmplx(int sptr, int putval)
905 {
906   fprintf(ASMFIL, " {float, float} {");
907   put_float(CONVAL1G(sptr));
908   fprintf(ASMFIL, ",");
909   put_float(CONVAL2G(sptr));
910   fprintf(ASMFIL, "}");
911 }
912 
913 static void
put_double_cmplx(int sptr,int putval)914 put_double_cmplx(int sptr, int putval)
915 {
916   fprintf(ASMFIL, " {double, double} {");
917   put_double(CONVAL1G(sptr));
918   fprintf(ASMFIL, ",");
919   put_double(CONVAL2G(sptr));
920   fprintf(ASMFIL, "}");
921 }
922 
923 static void
put_dcmplx_n(int sptr,int putval)924 put_dcmplx_n(int sptr, int putval)
925 {
926   put_r8((int)CONVAL1G(sptr), putval);
927   fprintf(ASMFIL, ",");
928   put_r8((int)CONVAL2G(sptr), putval);
929 }
930 
931 /**
932    \brief Generate an expression to add an offset to a ptr
933    \param offset    the addend
934    \param ret_type  the type of the pointer (LL_Type)
935    \param ptr_nm    the identifier for the pointer
936 
937    For example,
938    <pre>
939      getelementptr(i8* bitcast(<ret_type> <ptr_nm> to i8*), i32 <offset>)
940    </pre>
941 
942    The caller expects a string that is an i8*.
943  */
944 LL_Value *
gen_ptr_offset_val(int offset,LL_Type * ret_type,char * ptr_nm)945 gen_ptr_offset_val(int offset, LL_Type *ret_type, char *ptr_nm)
946 {
947   /* LL_Type for i8* (used as bitcast target for GEP to get byte offsets) */
948   LL_Type *ll_type_i8_ptr =
949       ll_get_pointer_type(ll_create_int_type(cpu_llvm_module, 8));
950 
951   /* Create an LL_Value from LL_Type ... */
952   LL_Value *llv = ll_create_value_from_type(cpu_llvm_module, ret_type, ptr_nm);
953   /*... and use it to generate a bitcast instruction to i8* */
954   llv = ll_get_const_bitcast(cpu_llvm_module, llv, ll_type_i8_ptr);
955   /*... then use it to generate a GEP instruction to get element at a byte
956    * offset */
957   llv = ll_get_const_gep(cpu_llvm_module, llv, 1, offset);
958   return llv;
959 }
960 
961 /**
962    \brief Produce a getelementptr that would fetch a value out of one of the
963    global structs.
964 
965    Print something along the lines of (LLVM version dependent):
966    \verbatim
967      getelementptr (i8* bitcast (%struct$name* @getsname(sptr)
968                     to i8*), i32 0) to i8*)
969    \endverbatim
970  */
971 void
put_addr(SPTR sptr,ISZ_T off,DTYPE dtype)972 put_addr(SPTR sptr, ISZ_T off, DTYPE dtype)
973 {
974   const char *name, *elem_type;
975   bool is_static_or_common_block_var, in_fortran;
976 
977   in_fortran = false;
978   in_fortran = true;
979 
980   /* Static and common block variables require special handling for now */
981   is_static_or_common_block_var = (SCG(sptr) == SC_STATIC);
982 #ifdef SC_CMBLK
983   is_static_or_common_block_var =
984       is_static_or_common_block_var || (SCG(sptr) == SC_CMBLK);
985 #endif
986 
987   elem_type = "";
988   /* Decide whether we need to provide element type to GEP */
989   if (ll_feature_explicit_gep_load_type(&cpu_llvm_module->ir))
990     elem_type = "i8, ";
991 
992   if (sptr) {
993     if ((name = getsname(sptr))) {
994       if (is_static_or_common_block_var && in_fortran) {
995         /* Statics and common block initializations in Fortran are
996          * strings composed using fprintf;
997          * FIXME need to generate them using LL_Value, like below */
998 
999         /* Statics and common blocks in fortran as stored as structs, we need to
1000          * add offset inside of struct */
1001         off += ADDRESSG(sptr);
1002 
1003         /* Text type for contansts is produced via char_type */
1004         if (STYPEG(sptr) == ST_CONST)
1005           fprintf(ASMFIL,
1006                   "getelementptr(%si8* bitcast (%s* @%s to i8*), i32 %ld)",
1007                   elem_type, char_type(DTYPEG(sptr), sptr), name, off);
1008         /* Structures have type name mirroring variable name */
1009         else
1010           fprintf(
1011               ASMFIL,
1012               "getelementptr(%si8* bitcast (%%struct%s* @%s to i8*), i32 %ld)",
1013               elem_type, name, name, off);
1014       } else {
1015         /* Convert to LLVM-compatible structures */
1016         if (!LLTYPE(sptr)) {
1017           process_sptr(sptr);
1018         }
1019 
1020         LL_Type *ll_type = LLTYPE(sptr);
1021 
1022         /* Convert to pointer type if needed
1023          * TODO implications of this are unclear, it works for now
1024          * because this is only used in data initialization */
1025         if (ll_type->data_type != LL_PTR && need_ptr(sptr, SCG(sptr), dtype))
1026           ll_type = ll_get_pointer_type(ll_type);
1027 
1028         /* Produce pointer offset code */
1029         LL_Value *ll_offset = gen_ptr_offset_val(off, ll_type, SNAME(sptr));
1030         fprintf(ASMFIL, "%s", ll_offset->data);
1031       }
1032     } else
1033       fprintf(ASMFIL, "null");
1034   } else if (off == 0)
1035     fprintf(ASMFIL, "null");
1036   else
1037     fprintf(ASMFIL, "%ld", (long)off);
1038 }
1039 
1040 DTYPE
mk_struct_for_llvm_init(const char * name,int size)1041 mk_struct_for_llvm_init(const char *name, int size)
1042 {
1043   int tag;
1044   DTYPE dtype;
1045   int gblsym;
1046   char sname[MXIDLN];
1047 
1048   snprintf(sname, sizeof(sname), "struct%s", name);
1049   dtype = cg_get_type(6, TY_STRUCT, NOSYM);
1050   tag = getsymbol(sname);
1051   DTYPEP(tag, dtype);
1052   DTY(dtype + 2) = 0; /* size */
1053   DTY(dtype + 3) = tag;
1054   DTY(dtype + 4) = 0; /* align */
1055   DTY(dtype + 5) = 0;
1056   if (size == 0)
1057     process_ftn_dtype_struct(dtype, sname, true);
1058   return dtype;
1059 }
1060 
1061 int
add_member_for_llvm(SPTR sym,int prev,DTYPE dtype,ISZ_T size)1062 add_member_for_llvm(SPTR sym, int prev, DTYPE dtype, ISZ_T size)
1063 {
1064   SPTR mem = insert_sym_first(sym);
1065   if (prev > NOSYM)
1066     SYMLKP(prev, mem);
1067   DTYPEP(mem, dtype);
1068   SYMLKP(mem, NOSYM);
1069   PSMEMP(mem, mem);
1070   VARIANTP(mem, prev);
1071   STYPEP(mem, ST_MEMBER);
1072   CCSYMP(mem, 1);
1073   ADDRESSP(mem, size);
1074   SCP(mem, SC_NONE);
1075   return mem;
1076 }
1077 
1078 /**
1079    \brief Add initilizer routine 'initroutine' to the llvm global ctor array
1080  */
1081 void
add_init_routine(char * initroutine)1082 add_init_routine(char *initroutine)
1083 {
1084   /* Current assumption is that initroutine has a type void with no argument.
1085      If type of init routine is not void and with argument then bitcast is
1086      needed.
1087    */
1088   llvm_ctor_add(initroutine);
1089 }
1090 
1091 /* Add the constructor responsible for initializing the libhugetlb
1092  * functionality.  The code behind the initialization exists in the following
1093  * directory: <pgi_root>/pds/libhugetlb/.
1094  */
1095 void
init_huge_tlb(void)1096 init_huge_tlb(void)
1097 {
1098   add_ctor("__pgi_huge_pages_init_zero");
1099 }
1100 
1101 /** \brief Add the constructor responsible for -Mflushz */
1102 void
init_flushz(void)1103 init_flushz(void)
1104 {
1105   add_ctor("__flushz");
1106 }
1107 
1108 /** \brief Add the constructor responsible for -Mdaz */
1109 void
init_daz(void)1110 init_daz(void)
1111 {
1112   add_ctor("__daz");
1113 }
1114 
1115 /** \brief Add the constructor responsible for -Ktrap */
1116 void
init_ktrap(void)1117 init_ktrap(void)
1118 {
1119   add_ctor("__ktrap");
1120   /* it would be better if there were a llutil process to ultimately emit
1121    * the global & its init  -- I know can create a symbol & dinit(), but
1122    * that's too much overhead.
1123    * A potential probleme is that the name may need an ABI adjustment. e.g,.
1124    * OSX prepends an underscore to user globals.
1125    */
1126   fprintf(ASMFIL, "@__ktrapval = global i32 %d, align 4\n", flg.x[24] & 0x1f9);
1127 }
1128 
1129