00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 #include <stdint.h>
00062 #include <ctype.h>
00063 #include "elf_stuff.h"
00064
00065 #define USE_STANDARD_TYPES 1
00066 #include "defs.h"
00067 #include "config_targ_opt.h"
00068 #include "targ_const.h"
00069 #include "targ_const_private.h"
00070 #include "vstring.h"
00071 #include "config_asm.h"
00072 #include "em_elf.h"
00073 #include "symtab.h"
00074 #include "tn.h"
00075 #include "cgemit.h"
00076 #include "cgemit_targ.h"
00077 #include "cgdwarf.h"
00078 #include "cgdwarf_targ.h"
00079 #include "data_layout.h"
00080 #include "bb.h"
00081 #include "op.h"
00082 #include "iface_scn.h"
00083 #include "cg_flags.h"
00084 #include "glob.h"
00085 #include "sections.h"
00086 #include "targ_isa_print.h"
00087 #include "config_debug.h"
00088 #include "cgtarget.h"
00089 #include "tracing.h"
00090 #include "erglob.h"
00091 #include "erbe.h"
00092 #include "ttype.h"
00093 #include "whirl2ops.h"
00094
00095 static void CGEMIT_Function_Prototype (ST*);
00096
00097 static ST *current_pu = NULL;
00098
00099 static BOOL
00100 Non_Default_Text_Section (ST *pu)
00101 {
00102 if (!pu || !ST_base(pu))
00103 return FALSE;
00104
00105 return ((ST_sclass(ST_base(pu)) == SCLASS_TEXT) &&
00106 strcmp(ST_name(ST_base(pu)), ".text"));
00107 }
00108
00109
00110 void
00111 CGEMIT_Targ_Initialize (ST *pu)
00112 {
00113 current_pu = pu;
00114 }
00115
00116
00117 void
00118 CGEMIT_Targ_Text_Initialize (ST *pu)
00119 {
00120 if (Non_Default_Text_Section(pu))
00121 fprintf (Asm_File, "\t.begin\tliteral_prefix %s\n", ST_name(ST_base(pu)));
00122 }
00123
00124
00125 void
00126 CGEMIT_Targ_Text_Finalize (ST *pu)
00127 {
00128 if (Non_Default_Text_Section(pu))
00129 fprintf (Asm_File, "\t.end\tliteral_prefix\n");
00130 }
00131
00132
00133 BOOL
00134 CGEMIT_Align_Section_Once (const char *scn_name)
00135 {
00136 return strcmp(scn_name, ".literal") && strcmp(scn_name, ".text");
00137 }
00138
00139 void
00140 CGEMIT_Prn_File_Dir_In_Asm(USRCPOS usrcpos,
00141 const char *pathname,
00142 const char *filename)
00143 {
00144 if (CG_emit_non_gas_syntax)
00145 fprintf (Asm_File, "\t%s\t%d\t\"%s/%s\"\n",
00146 AS_FILE, USRCPOS_filenum(usrcpos)-1, pathname, filename);
00147 else fprintf (Asm_File, "\t%s\t%d\t\"%s/%s\"\n",
00148 AS_FILE, USRCPOS_filenum(usrcpos), pathname, filename);
00149 }
00150
00151 extern void
00152 CGEMIT_Prn_Line_Dir_In_Asm (USRCPOS usrcpos)
00153 {
00154 if (CG_emit_non_gas_syntax)
00155 fprintf (Asm_File, "\t.loc\t%d\t%d\t%d\n",
00156 USRCPOS_filenum(usrcpos)-1,
00157 USRCPOS_linenum(usrcpos),
00158 USRCPOS_column(usrcpos));
00159 else
00160 fprintf (Asm_File, "\t.loc\t%d\t%d\t%d\n",
00161 USRCPOS_filenum(usrcpos),
00162 USRCPOS_linenum(usrcpos),
00163 USRCPOS_column(usrcpos));
00164 }
00165
00166
00167 void
00168 CGEMIT_Prn_Scn_In_Asm (ST *st, ST *cur_section)
00169 {
00170 UINT32 tmp, power;
00171
00172
00173
00174 {
00175 char *name = ST_name(st);
00176 if (strstr(name, "__libc_") == name)
00177 return;
00178 }
00179 power = 0;
00180 for (tmp = STB_align(st); tmp > 1; tmp >>= 1) power++;
00181 CGEMIT_Prn_Scn_In_Asm(Asm_File,
00182 ST_name(st),
00183 Get_Section_Elf_Type(STB_section_idx(st)),
00184 Get_Section_Elf_Flags(STB_section_idx(st)),
00185 Get_Section_Elf_Entsize(STB_section_idx(st)),
00186 power,
00187 (cur_section != NULL) ? ST_name(cur_section) : NULL);
00188 }
00189
00190 void
00191 CGEMIT_Prn_Scn_In_Asm (FILE *asm_file,
00192 const char *scn_name,
00193 Elf64_Word scn_type,
00194 Elf64_Word scn_flags,
00195 Elf64_Xword scn_entsize,
00196 Elf64_Word scn_align,
00197 const char *cur_scn_name)
00198 {
00199
00200
00201 if ( ! Is_Dwarf_Section_To_Emit(scn_name))
00202 return;
00203
00204
00205 {
00206 char scn_flags_string[5];
00207 char *p = &scn_flags_string[0];
00208
00209 fprintf (asm_file, "\n \t//DWARF %s %s", AS_SECTION, scn_name);
00210 if (CG_emit_non_gas_syntax && strcmp(scn_name, ".srdata") == 0) {
00211 static BOOL printed = FALSE;
00212 if (!printed) {
00213 fprintf(asm_file, ", %d, %#x, %" LL_FORMAT "d, ",
00214 scn_type, scn_flags, (UINT64) scn_entsize);
00215 int tmp1 = 1, tmp2 = scn_align;
00216 for (; tmp2 >= 1; tmp1 *= 2, tmp2 --);
00217 fprintf(asm_file, "%d", tmp1);
00218 printed = TRUE;
00219 }
00220 }
00221 if (! CG_emit_non_gas_syntax) {
00222 if (scn_flags & SHF_WRITE) *p++ = 'w';
00223 if (scn_flags & SHF_ALLOC) *p++ = 'a';
00224 if (scn_flags & SHF_EXECINSTR) *p++ = 'x';
00225 *p = '\0';
00226 fprintf (asm_file, ", \"%s\"", scn_flags_string);
00227 if (scn_type == SHT_PROGBITS)
00228 fprintf (asm_file, ",@progbits");
00229 }
00230 if (strcmp(scn_name, ".debug_frame") == 0)
00231 fprintf(asm_file, "\n.LCIE:");
00232 }
00233
00234 fprintf (asm_file, "\n");
00235
00236
00237
00238
00239
00240
00241 if (!CGEMIT_Align_Section_Once(scn_name))
00242 fprintf (asm_file, "\t//DWARF %s\t%d\n", AS_ALIGN, scn_align);
00243 }
00244
00245 void
00246 CGEMIT_Change_Origin_In_Asm (ST *st, INT64 offset)
00247 {
00248
00249
00250 #define EH_REGION_LINKONCE_PREFIX ".gnu.linkonce.e."
00251 #define EH_DESC_LINKONCE_PREFIX ".gnu.linkonce.h."
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 if (strcmp(ST_name(st), ".literal") &&
00265 strcmp(ST_name(st), ".xt_except_table") &&
00266 strcmp(ST_name(st), ".xt_desc_table") &&
00267 strncmp(ST_name(st), EH_REGION_LINKONCE_PREFIX,
00268 strlen(EH_REGION_LINKONCE_PREFIX)) &&
00269 strncmp(ST_name(st), EH_DESC_LINKONCE_PREFIX,
00270 strlen(EH_DESC_LINKONCE_PREFIX)))
00271 {
00272 if (CG_emit_non_gas_syntax)
00273 fprintf (Asm_File, "\t%s 0x%" LL_FORMAT "x\n", ".origin", offset);
00274 else fprintf (Asm_File, "\t%s 0x%" LL_FORMAT "x\n", AS_ORIGIN, offset);
00275 fprintf ( Asm_File, "\t%s\t0\n", AS_ALIGN );
00276 }
00277 }
00278
00279
00280
00281 extern BOOL
00282 CGEMIT_Use_Base_ST_For_Reloc (INT reloc, ST *st)
00283 {
00284
00285
00286 if (ST_sclass(st) == SCLASS_TEXT)
00287 return FALSE;
00288 else
00289 return ST_is_export_local(st);
00290 }
00291
00292
00293 extern INT
00294 CGEMIT_Relocs_In_Asm (TN *t, ST *st, vstring *buf, INT64 *val)
00295 {
00296 INT paren = 1;
00297
00298
00299 if (ST_class(st) == CLASS_BLOCK && STB_section(st)) {
00300 *val -= GP_DISP;
00301 }
00302 switch (TN_relocs(t)) {
00303 case TN_RELOC_GOT_DISP:
00304 *buf = vstr_concat (*buf, "%got_disp");
00305 break;
00306 case TN_RELOC_GOT_PAGE:
00307 *buf = vstr_concat (*buf, "%got_page");
00308 break;
00309 case TN_RELOC_GOT_OFST:
00310 *buf = vstr_concat (*buf, "%got_ofst");
00311 break;
00312 case TN_RELOC_HI_GPSUB:
00313 *buf = vstr_concat (*buf, "%hi(%neg(%gp_rel");
00314 paren += 2;
00315 break;
00316 case TN_RELOC_LO_GPSUB:
00317 *buf = vstr_concat (*buf, "%lo(%neg(%gp_rel");
00318 paren += 2;
00319 break;
00320 case TN_RELOC_GPREL16:
00321 *buf = vstr_concat (*buf, "%gp_rel");
00322 break;
00323 case TN_RELOC_HIGH16:
00324 *buf = vstr_concat (*buf, "%hi");
00325 break;
00326 case TN_RELOC_LOW16:
00327 *buf = vstr_concat (*buf, "%lo");
00328 break;
00329 default:
00330 #pragma mips_frequency_hint NEVER
00331 FmtAssert (FALSE, ("relocs_asm: illegal reloc TN"));
00332
00333 }
00334 *buf = vstr_concat (*buf, "(" );
00335 *buf = vstr_concat (*buf, ST_name(st));
00336 *buf = vstr_concat (*buf, Symbol_Name_Suffix);
00337 return paren;
00338 }
00339
00340
00341 extern void
00342 CGEMIT_Relocs_In_Object (TN *t, ST *st, INT32 PC, pSCNINFO PU_section, INT64 *val)
00343 {
00344 FmtAssert(FALSE, ("NYI"));
00345 }
00346
00347
00348 extern void
00349 CGEMIT_Add_Call_Information (OP *op, BB *bb, INT32 PC, pSCNINFO PU_section)
00350 {
00351 ANNOTATION *ant = ANNOT_Get (BB_annotations(bb), ANNOT_CALLINFO);
00352 ST *call_sym = CALLINFO_call_st(ANNOT_callinfo(ant));
00353 Elf_Event_Kind event_type;
00354
00355 if (call_sym == NULL) return;
00356 if (ST_is_export_local(call_sym)) {
00357 event_type = EK_FCALL_LOCAL;
00358 }
00359 else {
00360 event_type = EK_FCALL_EXTERN;
00361 }
00362 Em_Add_New_Event (event_type, PC, EMT_Put_Elf_Symbol(call_sym),
00363 0, 0, PU_section);
00364
00365
00366
00367
00368
00369
00370 Em_Add_New_Rela (EMT_Put_Elf_Symbol(call_sym),
00371 R_IA_64_PCREL21B, PC, 0, PU_section);
00372
00373 }
00374
00375
00376
00377 void
00378 CGEMIT_Gen_Asm_Frame (INT64 frame_len)
00379 {
00380
00381 }
00382
00383
00384
00385 void
00386 CGEMIT_Prn_Ent_In_Asm (ST *pu)
00387 {
00388 FmtAssert(false, ("No AS_ENT for x86_64"));
00389 }
00390
00391
00392
00393 void
00394 STACK_FP_Fixup_PU()
00395 {}
00396
00397 void
00398 CGEMIT_Weak_Alias (ST *sym, ST *strongsym)
00399 {
00400 fprintf ( Asm_File, "\t%s\t%s\n", AS_WEAK, ST_name(sym));
00401 fprintf ( Asm_File, "\t%s = %s", ST_name(sym), ST_name(strongsym));
00402 if (ST_is_export_local(strongsym) && ST_class(strongsym) == CLASS_VAR) {
00403
00404 if (ST_level(strongsym) == GLOBAL_SYMTAB)
00405 fprintf ( Asm_File, "%s%d", Label_Name_Separator, ST_index(strongsym));
00406 else
00407 fprintf ( Asm_File, "%s%d%s%d", Label_Name_Separator,
00408 ST_pu(Get_Current_PU_ST()),
00409 Label_Name_Separator, ST_index(strongsym));
00410 }
00411 fprintf ( Asm_File, "\n");
00412 }
00413
00414 void CGEMIT_Write_Literal_TCON(ST *lit_st, TCON tcon)
00415 {
00416 INT64 val;
00417 if (TCON_ty(tcon) == MTYPE_F4)
00418 val = TCON_word0(tcon);
00419 else if ((TCON_ty(tcon) == MTYPE_I4) || (TCON_ty(tcon) == MTYPE_U4))
00420 val = TCON_v0(tcon);
00421 else
00422 FmtAssert(FALSE, ("Invalid literal value"));
00423 fprintf ( Asm_File, "\t%s\t", ".literal");
00424 EMT_Write_Qualified_Name(Asm_File, lit_st);
00425 if ((val >= INT32_MIN) && (val <= INT32_MAX))
00426 fprintf(Asm_File, ", %" LL_FORMAT "d\n", val);
00427 else
00428 fprintf(Asm_File, ", %#" LL_FORMAT "x\n", val);
00429
00430 }
00431
00432 void CGEMIT_Write_Literal_Label (ST *lit_st, LABEL_IDX lab)
00433 {
00434 fprintf ( Asm_File, "\t%s\t", ".literal");
00435 EMT_Write_Qualified_Name(Asm_File, lit_st);
00436 union {
00437 UINT64 u;
00438 void *p;
00439 } u;
00440 u.u = 0;
00441 u.p = LABEL_name(lab);
00442 fprintf(Asm_File, ", %" LL_FORMAT "d\n", u.u);
00443 }
00444
00445 void CGEMIT_Write_Literal_Symbol (ST *lit_st, ST *sym,
00446 Elf64_Sxword sym_ofst)
00447 {
00448 ST *basesym;
00449 basesym = sym;
00450 INT64 base_ofst = 0;
00451
00452 if (Has_Base_Block(sym) && ST_is_export_local(sym) && ST_class(sym) != CLASS_FUNC) {
00453 Base_Symbol_And_Offset (sym, &basesym, &base_ofst);
00454 }
00455 base_ofst += sym_ofst;
00456
00457 fprintf ( Asm_File, "\t%s\t", ".literal");
00458 EMT_Write_Qualified_Name(Asm_File, lit_st);
00459 fprintf ( Asm_File, ", ");
00460 if (ST_class(sym) == CLASS_CONST) {
00461 EMT_Write_Qualified_Name (Asm_File, basesym);
00462 if (base_ofst == 0)
00463 fprintf (Asm_File, "\n");
00464 else
00465 fprintf (Asm_File, " %+lld\n", base_ofst);
00466 }
00467 else {
00468 EMT_Write_Qualified_Name (Asm_File, sym);
00469 if (sym_ofst == 0)
00470 fprintf (Asm_File, "\n");
00471 else
00472 fprintf (Asm_File, " %+lld\n", (INT64) sym_ofst);
00473 }
00474 }
00475
00476 void CGEMIT_Alias (ST *sym, ST *strongsym)
00477 {
00478 fprintf ( Asm_File, "\t%s = %s\n", ST_name(sym), ST_name(strongsym));
00479 }
00480
00481 void CGEMIT_Global_Decls (void)
00482 {
00483
00484
00485
00486 fprintf(Asm_File, "\n");
00487 fprintf(Asm_File, "\t.reg .u32 %%ra<17>;\n");
00488 fprintf(Asm_File, "\t.reg .u64 %%rda<17>;\n");
00489 fprintf(Asm_File, "\t.reg .f32 %%fa<17>;\n");
00490 fprintf(Asm_File, "\t.reg .f64 %%fda<17>;\n");
00491 fprintf(Asm_File, "\t.reg .u32 %%rv<5>;\n");
00492 fprintf(Asm_File, "\t.reg .u64 %%rdv<5>;\n");
00493 fprintf(Asm_File, "\t.reg .f32 %%fv<5>;\n");
00494 fprintf(Asm_File, "\t.reg .f64 %%fdv<5>;\n");
00495 fprintf(Asm_File, "\n");
00496
00497
00498 INT i;
00499 ST *sym;
00500 FOREACH_SYMBOL (GLOBAL_SYMTAB, sym, i) {
00501 if (ST_class(sym) == CLASS_FUNC
00502 && ST_is_export_local(sym)
00503 && !ST_is_not_used(sym)
00504 && PU_no_inline(ST_pu(sym))
00505 && TY_has_prototype(ST_pu_type(sym)))
00506 {
00507 CGEMIT_Function_Prototype(sym);
00508 }
00509 }
00510 }
00511
00512 static char*
00513 Register_Type_Name (ISA_REGISTER_CLASS rc)
00514 {
00515 switch (rc) {
00516 case ISA_REGISTER_CLASS_integer:
00517 return ".u32";
00518 case ISA_REGISTER_CLASS_integer16:
00519 return ".u16";
00520 case ISA_REGISTER_CLASS_integer64:
00521 return ".u64";
00522 case ISA_REGISTER_CLASS_float:
00523 return ".f32";
00524 case ISA_REGISTER_CLASS_float64:
00525 return ".f64";
00526 case ISA_REGISTER_CLASS_predicate:
00527 return ".pred";
00528 default:
00529 FmtAssert(FALSE, ("unexpected register class"));
00530 }
00531 }
00532
00533 static
00534 void CGEMIT_Register_Definitions (void)
00535 {
00536 ISA_REGISTER_CLASS rc;
00537 REGISTER reg;
00538 INT i;
00539 FOR_ALL_ISA_REGISTER_CLASS(rc) {
00540 reg = Last_Reg_Allocated(rc);
00541 if (reg != REGISTER_UNDEFINED) {
00542 fprintf(Asm_File, "\t.reg ");
00543 fprintf(Asm_File, "%s ", Register_Type_Name(rc));
00544
00545 char rname[16];
00546 strcpy(rname, REGISTER_name(rc,reg));
00547 char *p = rname;
00548 for (; !isdigit(*p); ++p)
00549 ;
00550 *p = '\0';
00551 fprintf(Asm_File, "%s<%d>;\n", rname, reg+1);
00552 }
00553 }
00554 }
00555
00556 void
00557 CGEMIT_Function_Prototype (ST *pu)
00558 {
00559 FmtAssert(!ST_in_global_mem(pu), ("only do prototypes for called functions"));
00560
00561 INT i;
00562 TN *tn;
00563 ISA_REGISTER_CLASS rc;
00564 fprintf ( Asm_File, "\n\t.func (");
00565 RETURN_INFO return_info = Get_Return_Info (TY_ret_type(ST_pu_type(pu)),
00566 No_Simulated);
00567 for (i = 0; i < RETURN_INFO_count(return_info); i++) {
00568 tn = PREG_To_TN (
00569 MTYPE_To_PREG(RETURN_INFO_mtype(return_info,i)),
00570 RETURN_INFO_preg (return_info, i));
00571 rc = TN_register_class(tn);
00572 if (i > 0) fprintf (Asm_File, ", ");
00573 fprintf ( Asm_File, ".reg %s %s",
00574 Register_Type_Name(rc),
00575 ABI_PROPERTY_Reg_Name(rc, REGISTER_machine_id(rc, TN_register(tn))));
00576 }
00577
00578 fprintf ( Asm_File, ") %s (", ST_name(pu) );
00579 i = 0;
00580 PLOC ploc;
00581 ploc = Setup_Input_Parameter_Locations (ST_pu_type(pu));
00582 TYLIST_IDX tl = TY_parms(ST_pu_type(pu));
00583 if (tl != (TYLIST_IDX) NULL) {
00584 i = 0;
00585 for (; TYLIST_ty(tl); tl = TYLIST_next(tl)) {
00586 TY_IDX ty = TYLIST_ty(tl);
00587 ploc = Get_Input_Parameter_Location (ty);
00588 ploc = First_Input_PLOC_Reg (ploc, ty);
00589 while (PLOC_is_nonempty(ploc)) {
00590 FmtAssert(!PLOC_on_stack(ploc), ("stack params not supported"));
00591 if (i > 0) fprintf (Asm_File, ", ");
00592 ++i;
00593 tn = PREG_To_TN(ty,PLOC_reg(ploc));
00594 rc = TN_register_class(tn);
00595 fprintf ( Asm_File, ".reg %s %s",
00596 Register_Type_Name(rc),
00597 ABI_PROPERTY_Reg_Name(rc,REGISTER_machine_id(rc, TN_register(tn))));
00598 ploc = Next_Input_PLOC_Reg (ploc);
00599 }
00600 }
00601 }
00602 fprintf ( Asm_File, ")\n");
00603 }
00604
00605 void
00606 CGEMIT_Function_Definition (ST *pu)
00607 {
00608 if (ST_in_global_mem(pu)) {
00609 fprintf ( Asm_File, "\n\t.entry %s\n", ST_name(pu) );
00610 } else {
00611 CGEMIT_Function_Prototype(pu);
00612 }
00613 fprintf ( Asm_File, "\t{\n");
00614 CGEMIT_Register_Definitions();
00615 }
00616
00617 void
00618 CGEMIT_Call (OP *op)
00619 {
00620
00621 INT i;
00622 TN *tn;
00623 ISA_REGISTER_CLASS rc;
00624 ST *call_st = TN_var(OP_opnd(op,0));
00625 TY_IDX func_ty = ST_pu_type(call_st);
00626 if (OP_code(op) == TOP_call)
00627 fprintf(Asm_File, "\tcall ");
00628 else if (OP_code(op) == TOP_call_uni)
00629 fprintf(Asm_File, "\tcall.uni ");
00630 else
00631 FmtAssert(FALSE, ("NYI"));
00632
00633 RETURN_INFO return_info = Get_Return_Info(TY_ret_type(func_ty), No_Simulated);
00634 if (RETURN_INFO_count(return_info) > 0) {
00635 fprintf(Asm_File, "(");
00636 for (i = 0; i < RETURN_INFO_count(return_info); i++) {
00637 if (i > 0) fprintf (Asm_File, ", ");
00638 tn = PREG_To_TN (
00639 MTYPE_To_PREG(RETURN_INFO_mtype(return_info,i)),
00640 RETURN_INFO_preg (return_info, i));
00641 rc = TN_register_class(tn);
00642 fprintf ( Asm_File, "%s",
00643 ABI_PROPERTY_Reg_Name(rc, REGISTER_machine_id(rc, TN_register(tn))));
00644 }
00645 fprintf(Asm_File, "), ");
00646 }
00647
00648 fprintf(Asm_File, "%s", ST_name(call_st));
00649
00650 PLOC ploc = Setup_Output_Parameter_Locations (func_ty);
00651 TYLIST_IDX tl = TY_parms(func_ty);
00652 if (tl != (TYLIST_IDX) NULL) {
00653 fprintf(Asm_File, ", (");
00654 i = 0;
00655 for (; TYLIST_ty(tl); tl = TYLIST_next(tl)) {
00656 TY_IDX ty = TYLIST_ty(tl);
00657 ploc = Get_Output_Parameter_Location(ty);
00658 ploc = First_Output_PLOC_Reg (ploc, ty);
00659 while (PLOC_is_nonempty(ploc)) {
00660 FmtAssert(!PLOC_on_stack(ploc), ("stack params not supported"));
00661 if (i > 0) fprintf (Asm_File, ", ");
00662 ++i;
00663 tn = PREG_To_TN(ty,PLOC_reg(ploc));
00664 rc = TN_register_class(tn);
00665 fprintf ( Asm_File, "%s",
00666 ABI_PROPERTY_Reg_Name(rc,REGISTER_machine_id(rc, TN_register(tn))));
00667 ploc = Next_Output_PLOC_Reg (ploc);
00668 }
00669 }
00670 fprintf(Asm_File, ")");
00671 }
00672 fprintf(Asm_File, ";\n");
00673 }
00674
00675 static BOOL
00676 Is_Dynamic_Size_Shared_Array (ST *st)
00677 {
00678
00679
00680 TY_IDX ty = ST_type(st);
00681 if ( ! ST_in_shared_mem(st))
00682 return FALSE;
00683 if (TY_kind(ty) != KIND_ARRAY)
00684 return FALSE;
00685 if ( ! TY_AR_const_ubnd(ty,TY_AR_ndims(ty)-1))
00686 return TRUE;
00687 return FALSE;
00688 }
00689
00690
00691
00692 static UINT total_const_size = 0;
00693
00694 static void
00695 CGEMIT_Print_Variable_Info (ST *st)
00696 {
00697 TY_IDX ty = ST_type(st);
00698 TYPE_ID mtype = TY_mtype(ty);
00699
00700 if (Get_Trace ( TP_EMIT, 4 )) {
00701 fprintf(TFile, "<emit> print variable %s\n", ST_name(st));
00702 }
00703
00704 if (ST_in_global_mem(st)) {
00705 fprintf(Asm_File, "\t.global ");
00706 }
00707 else if (ST_in_shared_mem(st)) {
00708 if (ST_sclass(st) == SCLASS_FORMAL)
00709 fprintf(Asm_File, "\t.param ");
00710 else
00711 fprintf(Asm_File, "\t.shared ");
00712 }
00713 else if (ST_in_local_mem(st)) {
00714 fprintf(Asm_File, "\t.local ");
00715 }
00716 else if (ST_in_constant_mem(st)) {
00717 fprintf(Asm_File, "\t.const ");
00718 }
00719 else if (ST_in_texture_mem(st)) {
00720 fprintf(Asm_File, "\t.tex ");
00721 }
00722 else {
00723 FmtAssert(FALSE, ("unexpected variable memory space"));
00724 }
00725
00726 if (TY_kind(ty) == KIND_ARRAY || TY_kind(ty) == KIND_STRUCT) {
00727
00728
00729 mtype = MTYPE_V;
00730 }
00731
00732 switch (mtype) {
00733 case MTYPE_I1: fprintf(Asm_File, ".s8"); break;
00734 case MTYPE_I2: fprintf(Asm_File, ".s16"); break;
00735 case MTYPE_I4: fprintf(Asm_File, ".s32"); break;
00736 case MTYPE_I8: fprintf(Asm_File, ".s64"); break;
00737 case MTYPE_U1: fprintf(Asm_File, ".u8"); break;
00738 case MTYPE_U2: fprintf(Asm_File, ".u16"); break;
00739 case MTYPE_U4: fprintf(Asm_File, ".u32"); break;
00740 case MTYPE_U8: fprintf(Asm_File, ".u64"); break;
00741 case MTYPE_F4: fprintf(Asm_File, ".f32"); break;
00742 case MTYPE_F8: fprintf(Asm_File, ".f64"); break;
00743 case MTYPE_V:
00744
00745 fprintf(Asm_File, ".align %d", TY_align(ty));
00746 fprintf(Asm_File, " .b8");
00747 break;
00748 default:
00749 FmtAssert(FALSE, ("NYI"));
00750 }
00751 if (ST_class(st) == CLASS_CONST)
00752 fprintf(Asm_File, " __constant%d", ST_index(st));
00753 else
00754 fprintf(Asm_File, " %s", ST_name(st));
00755
00756 if (Is_Dynamic_Size_Shared_Array(st)) {
00757 fprintf(Asm_File, "[]");
00758 } else if (TY_kind(ty) == KIND_ARRAY || TY_kind(ty) == KIND_STRUCT) {
00759 fprintf(Asm_File, "[%" LL_FORMAT "d]", TY_size(ty));
00760 if (ST_in_constant_mem(st))
00761 total_const_size += TY_size(ty);
00762 }
00763 else {
00764 if (ST_in_constant_mem(st))
00765 total_const_size += TY_size(ty);
00766 }
00767 if (total_const_size > 65536)
00768 ErrMsg (EC_Const_Space_Overflow);
00769 }
00770
00771 void CGEMIT_Print_TCON (TCON tcon, BOOL byte_array)
00772 {
00773 if (TCON_ty(tcon) == MTYPE_STRING) {
00774 INT i;
00775
00776 if (!byte_array) {
00777 fprintf(Asm_File, "{");
00778 }
00779 char *p = Targ_String_Address(tcon);
00780 for (i = 0; i < Targ_String_Length(tcon)-1; ++i, ++p)
00781 fprintf(Asm_File, "0x%x,", *p);
00782 fprintf(Asm_File, "0x%x", *p);
00783 if (!byte_array) {
00784 fprintf(Asm_File, "}");
00785 }
00786 }
00787 else if (byte_array) {
00788 INT64 val8;
00789 INT32 val4;
00790 INT16 val2;
00791 INT8 val1;
00792 float valf;
00793 double vald;
00794 INT i;
00795 char *p;
00796 switch (TCON_ty(tcon)) {
00797 case MTYPE_U1:
00798 case MTYPE_I1:
00799 val1 = (INT8) Targ_To_Host (tcon);
00800 fprintf(Asm_File, "%d", val1);
00801 break;
00802 case MTYPE_U2:
00803 case MTYPE_I2:
00804 val2 = (INT16) Targ_To_Host (tcon);
00805 p = (char*) &val2;
00806 fprintf(Asm_File, "%d,", *p);
00807 ++p;
00808 fprintf(Asm_File, "%d", *p);
00809 break;
00810 case MTYPE_U4:
00811 case MTYPE_I4:
00812 val4 = (INT32) Targ_To_Host (tcon);
00813 p = (char*) &val4;
00814 for (i = 0; i < 3; ++i, ++p)
00815 fprintf(Asm_File, "%d,", *p);
00816 fprintf(Asm_File, "%d", *p);
00817 break;
00818 case MTYPE_U8:
00819 case MTYPE_I8:
00820 val8 = (INT64) Targ_To_Host (tcon);
00821 p = (char*) &val8;
00822 for (i = 0; i < 7; ++i, ++p)
00823 fprintf(Asm_File, "%d,", *p);
00824 fprintf(Asm_File, "%d", *p);
00825 break;
00826 case MTYPE_F4:
00827 valf = (float) Targ_To_Host_Float (tcon);
00828 p = (char*) &valf;
00829 for (i = 0; i < 3; ++i, ++p)
00830 fprintf(Asm_File, "%d,", *p);
00831 fprintf(Asm_File, "%d", *p);
00832 break;
00833 case MTYPE_F8:
00834 vald = (double) Targ_To_Host_Float (tcon);
00835 p = (char*) &vald;
00836 for (i = 0; i < 7; ++i, ++p)
00837 fprintf(Asm_File, "%d,", *p);
00838 fprintf(Asm_File, "%d", *p);
00839 break;
00840 default:
00841 FmtAssert(FALSE, ("NYI"));
00842 }
00843 } else {
00844 fprintf(Asm_File, "%s", Targ_Print (NULL, tcon));
00845 if (MTYPE_is_float(TCON_ty(tcon))) {
00846 fprintf(Asm_File, " /* %s */", Targ_Print ("%g", tcon));
00847 }
00848 }
00849 }
00850
00851 void CGEMIT_Print_INITV (INITV_IDX inv, BOOL byte_array)
00852 {
00853
00854
00855 TCON tcon;
00856 UINT size = 0;
00857 UINT i;
00858 switch (INITV_kind(inv)) {
00859 case INITVKIND_ZERO:
00860 if (byte_array) {
00861 size = MTYPE_byte_size(INITV_mtype(inv)) * INITV_repeat(inv);
00862 for (i = 0; i < size-1; ++i)
00863 fprintf(Asm_File, "0,");
00864 fprintf(Asm_File, "0");
00865 } else {
00866 fprintf(Asm_File, "0");
00867 }
00868 break;
00869 case INITVKIND_PAD:
00870 size = INITV_pad(inv) * INITV_repeat(inv);
00871 for (i = 0; i < size-1; ++i)
00872 fprintf(Asm_File, "0,");
00873 fprintf(Asm_File, "0");
00874 break;
00875 case INITVKIND_ONE:
00876 if (byte_array) {
00877 size = MTYPE_byte_size(INITV_mtype(inv));
00878
00879 fprintf(Asm_File, "1");
00880 for (i = 0; i < size-1; ++i)
00881 fprintf(Asm_File, ",0");
00882 } else {
00883 fprintf(Asm_File, "1");
00884 }
00885 break;
00886 case INITVKIND_VAL:
00887 tcon = INITV_tc_val(inv);
00888 CGEMIT_Print_TCON(tcon, byte_array);
00889 break;
00890 case INITVKIND_BLOCK:
00891 if (!byte_array) {
00892 fprintf(Asm_File, "{");
00893 }
00894 for (INITV_IDX ninv = INITV_blk(inv); ninv; ninv = INITV_next(ninv)) {
00895 CGEMIT_Print_INITV (ninv, TRUE);
00896 if (INITV_next(ninv) != INITV_IDX_ZERO)
00897 fprintf(Asm_File, ",");
00898 }
00899 if (!byte_array) {
00900 fprintf(Asm_File, "}");
00901 }
00902 break;
00903 default:
00904 FmtAssert(FALSE, ("NYI initv kind %d", INITV_kind(inv)));
00905 }
00906 }
00907
00908 void CGEMIT_Print_Initialized_Variable (ST *st, INITO *ino)
00909 {
00910 INT count = 0;
00911 INITV_IDX inv;
00912 CGEMIT_Print_Variable_Info (st);
00913 fprintf(Asm_File, " = ");
00914 FmtAssert(INITO_val(*ino) != (INITO_IDX) NULL, ("NYI"));
00915 FOREACH_INITV (INITO_val(*ino), inv) {
00916 ++count;
00917 }
00918 if (count == 1) {
00919 CGEMIT_Print_INITV (INITO_val(*ino), FALSE);
00920 }
00921 else {
00922 fprintf(Asm_File, "{");
00923 FOREACH_INITV (INITO_val(*ino), inv) {
00924 CGEMIT_Print_INITV (inv, TRUE);
00925 if (INITV_next(inv) != INITV_IDX_ZERO)
00926 fprintf(Asm_File, ",");
00927 }
00928 fprintf(Asm_File, "}");
00929 }
00930 fprintf(Asm_File, ";\n");
00931 }
00932
00933 void CGEMIT_Print_Variable (ST *st)
00934 {
00935 if (Is_Dynamic_Size_Shared_Array(st)) {
00936
00937
00938 DevWarn("dynamic-sized array");
00939 fprintf(Asm_File, "\t.extern");
00940 }
00941 CGEMIT_Print_Variable_Info (st);
00942 if (ST_class(st) == CLASS_CONST) {
00943 TCON tc = ST_tcon_val(st);
00944 fprintf(Asm_File, " = {");
00945 CGEMIT_Print_TCON(tc, TRUE);
00946 fprintf(Asm_File, "}");
00947 }
00948 fprintf(Asm_File, ";\n");
00949 }
00950