/**************************************************************** * * * Copyright 2001, 2012 Fidelity Information Services, Inc * * * * This source code contains the intellectual property * * of its copyright holder(s), and is made available * * under a license. If you do not know the terms of * * the license, please stop and do not read further. * * * ****************************************************************/ #include "mdef.h" #include "gtm_fcntl.h" #include "gtm_stdio.h" #include #include "gtm_stat.h" #include #include "gtm_stdlib.h" #include "gtm_unistd.h" #include "compiler.h" #include "obj_gen.h" #include #include "cmd_qlf.h" #include "cgp.h" #include "gtmio.h" #include "eintr_wrappers.h" #include "mmemory.h" #include "obj_file.h" #include "alloc_reg.h" #include "jmp_opto.h" #include "mlabel2xtern.h" #include "cg_var.h" #include "gtm_string.h" #include "objlabel.h" #include "stringpool.h" #include "min_max.h" GBLDEF uint4 lits_text_size, lits_mval_size; IA64_DEBUG_ONLY(GBLREF int4 generated_count;) IA64_DEBUG_ONLY(GBLREF int4 calculated_count;) IA64_DEBUG_ONLY(GBLREF struct inst_count generated_details[MAX_CODE_COUNT];) IA64_DEBUG_ONLY(GBLREF struct inst_count calculated_details[MAX_CODE_COUNT];) IA64_ONLY(GBLREF int4 generated_code_size;) IA64_ONLY(GBLREF int4 calculated_code_size;) GBLREF int4 curr_addr, code_size; GBLREF char cg_phase; /* code generation phase */ GBLREF char cg_phase_last; /* previous code generation phase */ GBLREF boolean_t run_time; GBLREF command_qualifier cmd_qlf; GBLREF int4 mvmax, mlmax, mlitmax, sa_temps[], sa_temps_offset[]; GBLREF mlabel *mlabtab; GBLREF mline mline_root; GBLREF mvar *mvartab; GBLREF mident module_name, int_module_name; GBLREF int4 gtm_object_size; GBLREF int4 sym_table_size; GBLREF int4 linkage_size; GBLREF uint4 lnkrel_cnt; /* number of entries in linkage Psect to relocate */ GBLREF spdesc stringpool; #define PTEXT_OFFSET SIZEOF(rhdtyp) /* The sections of the internal GT.M object (sans native object wrapper) are grouped * according to their type (R/O-retain, R/O-release, R/W-retain, R/W-release). The * "retain"/"release" refers to whether the sections in that segment are retained if the * module is replaced by an explicit ZLINK. * * The GT.M object layout (in the native .text section) is as follows: * * +---------------+ * | rhead | > - R/O - retain * +---------------+ * | generated | \ * | code | \ * + - - - - - - - + | * | line num tbl | |- R/O releasable * + - - - - - - - + / * | lit text pool | / * +---------------+ * | lit mval tbl | \ * +---------------+ |- R/W releasable * | variable tbl | / * + - - - - - - - + * | label tbl | > - R/W retain * +---------------+ * | relocations | > - relocations for external syms (not kept after link) * +---------------+ * | symbol tbl | > - external symbol table (not kept after link) * +---------------+ * * Note in addition to the above layout, a "linkage section" is allocated at run time and is * also releasable. */ error_def(ERR_TEXT); void cg_lab (mlabel *mlbl, char *do_emit); void obj_code (uint4 src_lines, uint4 checksum) { int i; uint4 lits_pad_size, object_pad_size, lnr_pad_size; int4 offset; int4 old_code_size; rhdtyp rhead; mline *mlx, *mly; var_tabent *vptr; assert(!run_time); obj_init(); /* Define the routine name global symbol */ define_symbol(GTM_MODULE_DEF_PSECT, (mstr *)&int_module_name); memset(&rhead, 0, SIZEOF(rhead)); alloc_reg(); jmp_opto(); /* Note that this initial setting of curr_addr is historical in that the routine header was * contiguous with the code. This is no longer true and this address would be more correct * if it were set to zero however if that is done and the M code contains a branch or recursive * DO to the top of this routine, that branch will trigger an assert failure in emit_code * because a branch to "location 0" has long-jump implications. Keeping the initial offset * non-zero avoids this problem. We had to add PTEXT_OFFSET to curr_addr to get code_size * after the CGP_APPROX_ADDR phase anyway. Note that in using this offset, the rtaddr field * of the triples has a PTEXT_OFFSET origin so this will need to be accounted for when the * various tables below are generated using the rtaddr field. SE 10/2002 */ curr_addr = PTEXT_OFFSET; cg_phase = CGP_APPROX_ADDR; cg_phase_last = CGP_NOSTATE; IA64_ONLY(calculated_code_size = 0;) IA64_DEBUG_ONLY(calculated_count = 0;) code_gen(); code_size = curr_addr; cg_phase = CGP_ADDR_OPT; comp_lits(&rhead); old_code_size = code_size; shrink_trips(); IA64_ONLY ( if (old_code_size != code_size) calculated_code_size -= ((old_code_size - code_size)/16); ) if ((cmd_qlf.qlf & CQ_MACHINE_CODE)) { cg_phase = CGP_ASSEMBLY; code_gen(); } if (!(cmd_qlf.qlf & CQ_OBJECT)) return; /* Executable code offset setup */ IA64_ONLY(assert(!(PTEXT_OFFSET % SECTION_ALIGN_BOUNDARY));) rhead.ptext_adr = (unsigned char *)PTEXT_OFFSET; rhead.ptext_end_adr = (unsigned char *)(size_t)code_size; /* Line number table offset setup */ rhead.lnrtab_adr = (lnr_tabent *)rhead.ptext_end_adr; rhead.lnrtab_len = src_lines; code_size += src_lines * SIZEOF(lnr_tabent); lnr_pad_size = PADLEN(code_size, SECTION_ALIGN_BOUNDARY); code_size += lnr_pad_size; /* Literal text section offset setup */ rhead.literal_text_adr = (unsigned char *)(size_t)code_size; rhead.literal_text_len = lits_text_size; code_size += lits_text_size; assert(0 == PADLEN(code_size, NATIVE_WSIZE)); /* Literal mval section offset setup */ rhead.literal_adr = (mval *)(size_t)code_size; rhead.literal_len = lits_mval_size / SIZEOF(mval); code_size += lits_mval_size; /* Padding so variable table starts on proper boundary */ lits_pad_size = PADLEN(code_size, SECTION_ALIGN_BOUNDARY); code_size += lits_pad_size; /* Variable table offset setup */ rhead.vartab_adr = (var_tabent *)(size_t)code_size; rhead.vartab_len = mvmax; code_size += mvmax * SIZEOF(var_tabent); /* Linkage section setup. No table in object but need its length. */ rhead.linkage_adr = NULL; rhead.linkage_len = linkage_size / SIZEOF(lnk_tabent); /* Label table offset setup */ rhead.labtab_adr = (lab_tabent *)(size_t)code_size; rhead.labtab_len = mlmax; code_size += mlmax * SIZEOF(lab_tabent); if (mlabtab) walktree((mvar *)mlabtab, cg_lab, NULL); /* Prior to calculating reloc and symbol size, run the linkage chains to fill out * the reloc table and symbol table so we get the same size we will create later. */ comp_linkages(); /* Relocation table offset setup */ rhead.rel_table_off = code_size; code_size += lnkrel_cnt * SIZEOF(struct relocation_info); /* Symbol text list offset setup */ rhead.sym_table_off = code_size; assert(OUTPUT_SYMBOL_SIZE == output_symbol_size()); code_size += OUTPUT_SYMBOL_SIZE; /* Pad to OBJECT_SIZE_ALIGNMENT byte boundary.(Perhaps need for building into shared library -MR) */ object_pad_size = PADLEN(code_size, OBJECT_SIZE_ALIGNMENT); code_size += object_pad_size; gtm_object_size = code_size; rhead.checksum = checksum; rhead.objlabel = MAGIC_COOKIE; rhead.temp_mvals = sa_temps[TVAL_REF]; rhead.temp_size = sa_temps_offset[TCAD_REF]; rhead.compiler_qlf = cmd_qlf.qlf; /* Start the creation of the output object */ create_object_file(&rhead); cg_phase = CGP_MACHINE; IA64_ONLY(generated_code_size = 0;) IA64_DEBUG_ONLY(generated_count = 0;) code_gen(); IA64_DEBUG_ONLY( if (calculated_code_size != generated_code_size) { if (getenv("DUMP_CODE_SIZE_DIFFERENCE")) { PRINTF("Here is the instruction count for each triple type :\n"); for (i = 0; i < MAX(calculated_count, generated_count); i++) { if (calculated_details[i].size != generated_details[i].size || calculated_details[i].sav_in != generated_details[i].sav_in) PRINTF("[X]"); else PRINTF("[ ]"); } PRINTF("calculated (size = %d save_in = 0x%x) gen (size = %d save_in = 0x%x)\n", calculated_details[i].size, calculated_details[i].sav_in, generated_details[i].size, generated_details[i].sav_in); } else PRINTF("Set the env variable - DUMP_CODE_SIZE_DIFFERENCE - to see more details about the difference\n"); } ) IA64_ONLY(assert(calculated_code_size == generated_code_size)); /* External entry definitions (line number table */ offset = (int4)(mline_root.externalentry->rtaddr - PTEXT_OFFSET); emit_immed((char *)&offset, SIZEOF(offset)); /* line 0 */ for (mlx = mline_root.child; mlx; mlx = mly) { if (mlx->table) { offset = (int4)(mlx->externalentry->rtaddr - PTEXT_OFFSET); emit_immed((char *)&offset, SIZEOF(offset)); } if (0 == (mly = mlx->child)) /* note the assignment */ { if (0 == (mly = mlx->sibling)) /* note the assignment */ { for (mly = mlx; ; ) { if (0 == (mly = mly->parent)) /* note the assignment */ break; if (mly->sibling) { mly = mly->sibling; break; } } } } } if (lnr_pad_size) /* emit padding so literal text pool starts on proper boundary */ emit_immed(PADCHARS, lnr_pad_size); /* Both literal text pool and literal mval table */ emit_literals(); /* Emit padding so variable table starts on proper boundary */ assert(STR_LIT_LEN(PADCHARS) >= lits_pad_size); if (lits_pad_size) emit_immed(PADCHARS, lits_pad_size); /* Variable table: */ vptr = (var_tabent *)mcalloc(mvmax * SIZEOF(var_tabent)); if (mvartab) walktree(mvartab, cg_var, (char *)&vptr); emit_immed((char *)vptr, mvmax * SIZEOF(var_tabent)); /* The label table */ if (mlabtab) walktree((mvar *)mlabtab, cg_lab, (char *)TRUE); /* Resolve locally defined symbols */ resolve_sym(); /* Output relocation entries for the linkage section */ output_relocation(); /* Output the symbol table text pool */ output_symbol(); /* If there is padding we need to do to fill out the object to the required boundary do it.. */ if (object_pad_size) { assert(STR_LIT_LEN(PADCHARS) >= object_pad_size); emit_immed(PADCHARS, object_pad_size); } close_object_file(); } /* Routine called to process a given label. Cheezy 2nd parm is due to general purpose * mechanism of the walktree routine that calls us. */ void cg_lab(mlabel *mlbl, char *do_emit) { lab_tabent lent; mstr glob_name; if (mlbl->ml && mlbl->gbl) { if (do_emit) { /* Output (2nd) pass, emit the interesting information */ lent.lab_name.len = mlbl->mvname.len; lent.lab_name.addr = (char *)(mlbl->mvname.addr - (char *)stringpool.base); /* Offset into literal text pool */ lent.LABENT_LNR_OFFSET = (lnr_tabent *)(SIZEOF(lnr_tabent) * mlbl->ml->line_number); /* Offset into lnr table */ lent.has_parms = (NO_FORMALLIST != mlbl->formalcnt); /* Flag to indicate any formallist */ emit_immed((char *)&lent, SIZEOF(lent)); } else { /* 1st pass, do the definition but no emissions */ mlabel2xtern(&glob_name, &int_module_name, &mlbl->mvname); define_symbol(GTM_CODE, &glob_name); } } return; }