//******************************************************* // WGEN driver //******************************************************* int main ( INT argc, char **argv, char **envp) { INT error_count, sorry_count; BOOL need_inliner; struct stat sbuf; int st; Set_Error_Tables ( Phases, host_errlist ); Process_Command_Line(argc, argv); st = stat(Spin_File_Name, &sbuf); if (st == -1 && (errno == ENOENT || errno == ENOTDIR)) printf ("wgen: file %s does not exist\n", Spin_File_Name); else if ((program = gs_read_file (Spin_File_Name)) != (gs_t) NULL) { // gs_dump(program); Process_Cc1_Command_Line(gs_cc1_command_line_args(program)); WGEN_Init(argc, argv, envp); WGEN_File_Init(argc, argv); gs_t list = gs_operand(program, GS_PROGRAM_DECLARATIONS); // in bug 10185, first list node is NULL, so skip first node if (gs_code(list) != EMPTY) list = gs_operand(list, 1); for (; gs_code(list) != EMPTY; list = gs_operand(list, 1)) { gs_t decl = gs_operand(list, 0); WGEN_Expand_Top_Level_Decl(decl); #ifdef KEY WGEN_Expand_Defers(); #endif } #ifdef KEY if (!lang_cplus) WGEN_Alias_Finish(); #endif WGEN_Weak_Finish(); WGEN_File_Finish (); WGEN_Finish (); } else printf ("wgen: libspin returned (gs_t) NULL.\n"); WGEN_Check_Errors (&error_count, &sorry_count, &need_inliner); if (error_count) Terminate (RC_INTERNAL_ERROR) ; if (need_inliner && ((!Enable_WFE_DFE) || (Opt_Level > 1))) exit ( RC_NEED_INLINER ); exit (RC_OKAY); }
gs_unsigned_char_t *gs_read (const gs_string_t filename) { gs_int_t fd, fstat_rv; struct stat statbuf; char *p, *string_section, *maxptr; fd = open (filename, O_RDWR); GS_ASSERT (fd != -1, "open failed.\n"); fstat_rv = fstat (fd, &statbuf); // printf ("statbuf.st_size: %ld\n", statbuf.st_size); // printf ("struct gspin size: %u\n", sizeof (struct gspin)); GS_ASSERT (fstat_rv == 0, "fstat failed.\n"); mem_seg = mmap (0, statbuf.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); GS_ASSERT (mem_seg != MAP_FAILED, "mmap failure.\n"); GS_ASSERT (mem_seg != NULL, "mem_seg null!.\n"); // Convert indexes within the mem_seg to physical addresses. p = mem_seg; maxptr = (sizeof(void*) == sizeof(int))? (char*)UINT_MAX : (char*)ULONG_MAX; string_section = maxptr; //initialize the pointer with 0xff...ff while (p - mem_seg < statbuf.st_size && p < string_section) { gs_t q = (gs_t) p; if (gs_code_arity(gs_code(q)) > 0) { // convert kid indicese to pointers int j; for (j = 0; j < gs_code_arity(gs_code(q)); j++) if (gs_operand(q, j) != NULL) { GS_ASSERT((int)gs_operand(q, j) < statbuf.st_size, "right offset out of bounds!.\n"); gs_set_operand(q, j, (gs_t) (mem_seg + (long) gs_operand(q,j))); } } else if (gs_code(q) == IB_STRING) { // convert string index to pointer if (string_section == maxptr) //string section not found yet string_section = mem_seg + gs_u(q); GS_ASSERT(gs_u(q) < statbuf.st_size, "left offset out of bounds!.\n"); _gs_s_no_alloc (q, (gs_unsigned_char_t *) (mem_seg + gs_u(q))); } _gs_em(p, false); p += gspin_node_size(gs_code(q)); while (p - mem_seg < statbuf.st_size && p < string_section && gs_code((gs_t) p) == DOT) p += 4; } close (fd); return mem_seg; }
// Perform the function of GCC tree.c's build_pointer_type. gs_t gs_build_pointer_type(gs_t to_type) { gs_t t, type_pointer_to; gs_t error_mark_node = gs_error_mark_node(); gs_t ptr_type = gs_ptr_type_node(); gs_string_t ptr_type_mode = gs_type_mode(ptr_type); if (to_type == error_mark_node) return error_mark_node; // GCC returns NODE if the pointer_to type is not POINTER_TYPE. This case // does not occur in C/C++, type_pointer_to = gs_type_pointer_to(to_type); GS_ASSERT(!(type_pointer_to != NULL && gs_tree_code(type_pointer_to) != GS_POINTER_TYPE), ("gs_build_pointer_type: TYPE_POINTER_TO is not POINTER_TYPE")); for (t = type_pointer_to; t != NULL; t = gs_type_next_ptr_to(t)) { gs_string_t mode = gs_type_mode(t); if (!strcmp(mode, ptr_type_mode) && gs_type_ref_can_alias_all(t) == 0) { return t; } } t = gs_build_type(GS_POINTER_TYPE); gs_set_operand(t, GS_TREE_TYPE, to_type); { gs_t type_mode = __gs(IB_STRING); _gs_s (type_mode, ptr_type_mode, 1 + strlen((char *)ptr_type_mode)); gs_set_operand(t, GS_TYPE_MODE, type_mode); } gs_set_type_ref_can_alias_all(t, 0); gs_set_operand(t, GS_TYPE_NEXT_PTR_TO, gs_type_pointer_to(to_type)); gs_set_operand(to_type, GS_TYPE_POINTER_TO, t); // Copy pointer attributes from the generic pointer. { gs_t type_precision = __gs(IB_INT); gs_set_operand(t, GS_TYPE_SIZE, gs_operand(ptr_type, GS_TYPE_SIZE)); gs_set_operand(t, GS_TYPE_SIZE_UNIT, gs_operand(ptr_type, GS_TYPE_SIZE_UNIT)); gs_set_operand(t, GS_TYPE_ALIGN, gs_operand(ptr_type, GS_TYPE_ALIGN)); gs_set_type_unsigned(t, 1); _gs_n(type_precision, gs_type_type_precision(ptr_type)); gs_set_operand(t, GS_TYPE_PRECISION, type_precision); } return t; }
void flag_reachable_nodes(gs_t t) { if (t == NULL) return; if (gs_em(t) == true) return; _gs_em(t, true); int j; for (j = 0; j < gs_code_arity(gs_code(t)); j++) flag_reachable_nodes(gs_operand(t, j)); }
gs_tree_code_class_t gs_tree_code_class(gs_t t) { GS_ASSERT (t != (gs_t) NULL, "Got null node"); gs_tree_code_class_t tcc = (gs_tree_code_class_t) gs_b(gs_operand (t, GS_TREE_CODE_CLASS)); GS_ASSERT(tcc == tree_code_table[gs_code(t)].tcc, "Incorrect tree code class in tree_code_table"); #ifdef Is_True_On if (tcc != tree_code_table[gs_code(t)].tcc) { printf("%s should have tcc %s\n", gs_code_name(gs_code(t)), gs_tree_code_class_name(tcc)); abort(); } #endif return tcc; }
gs_void_t gs_write (const gs_string_t filename) { gs_count_t gs_length, unsigned_char_length, mem_seg_length; gs_int_t fd, lseek_rv, write_rv; #ifdef Is_True_On flag_reachable_nodes((gs_t) gs_mempool[GS_ARENA].firstblock->mem); #endif gs_arena_t *gs_arena = &gs_mempool[GS_ARENA]; gs_arena_t *gs_unsigned_char_arena = &gs_mempool[IB_STRING_ARENA]; gs_length = gs_arena->current_index; unsigned_char_length = gs_unsigned_char_arena->current_index; mem_seg_length = gs_length + unsigned_char_length; fd = open (filename, O_TRUNC|O_CREAT|O_RDWR, 0666); GS_ASSERT (!(fd < 0), "open failed.\n"); lseek_rv = lseek (fd, mem_seg_length - 1, SEEK_SET); GS_ASSERT (lseek_rv != -1, "lseek failed.\n"); write_rv = write (fd, " ", 1); GS_ASSERT (write_rv == 1, "write failed.\n"); mem_seg = mmap (0, mem_seg_length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); GS_ASSERT (mem_seg != MAP_FAILED, "mmap failure.\n"); // Convert physical addresses to indexes within the mem_seg. int i = 0; int size; gs_t p_in_memseg; gs_t t = (gs_t) gs_mempool_idx2address(GS_ARENA, 0); while (i < gs_arena->current_index) { p_in_memseg = (gs_t) (mem_seg + i); size = gspin_node_size(gs_code(t)); memcpy(p_in_memseg, t, size); #if 0 #ifdef Is_True_On _gs_em(p_in_memseg, false); if (gs_em(t) == false) { printf("leaked node: "); gs_dump(t); } #endif #endif if (gs_code_arity(gs_code(t)) > 0) { // convert kid pointers to indices int j; for (j = 0; j < gs_code_arity(gs_code(t)); j++) if (gs_operand(t, j) != NULL) gs_set_operand(p_in_memseg, j, (gs_t) gs_mempool_address2byteofst(GS_ARENA, (char *)gs_operand(t, j))); } else if (gs_code(t) == IB_STRING) { // convert string pointer to index gs_string_t s = gs_s(t); _gs_u(p_in_memseg, gs_length + gs_mempool_address2byteofst(IB_STRING_ARENA, s)); memcpy (mem_seg + gs_u(p_in_memseg), s, gs_slen(p_in_memseg)); } i += gspin_node_size(gs_code(t)); t = (gs_t) gs_mempool_idx2address(GS_ARENA, i); while (i < gs_arena->current_index && gs_code(t) == DOT) { i += 4; t = (gs_t) gs_mempool_idx2address(GS_ARENA, i); } } close (fd); return; }