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