diff options
-rw-r--r-- | cgaas.c | 309 | ||||
-rw-r--r-- | cgaas.h | 3 | ||||
-rw-r--r-- | cgcode.c | 595 | ||||
-rw-r--r-- | cgcodep.h | 1 | ||||
-rw-r--r-- | cginput.c | 1 | ||||
-rw-r--r-- | cginstructions.c | 41 | ||||
-rw-r--r-- | cglin.c | 4 | ||||
-rw-r--r-- | cgtypes.h | 13 |
8 files changed, 779 insertions, 188 deletions
@@ -210,6 +210,7 @@ static void write_q (int c) #endif #ifdef LINUX # define GOT_PC_RELATIVE_RELOCATION 13 +# define PLT_PC_RELATIVE_RELOCATION 14 #endif struct relocation { @@ -277,6 +278,16 @@ struct call_and_jump { static struct call_and_jump *first_call_and_jump,*last_call_and_jump; +#ifdef LINUX +struct got_jump { + struct got_jump *gj_next; + struct label *gj_got_label; + struct label gj_label; +}; + +static struct got_jump *first_got_jump,*last_got_jump; +#endif + void initialize_assembler (FILE *output_file_d) { output_file=output_file_d; @@ -298,6 +309,9 @@ void initialize_assembler (FILE *output_file_d) n_data_relocations=0; first_call_and_jump=NULL; +#ifdef LINUX + first_got_jump=NULL; +#endif #ifdef ELF string_table_offset=13; #else @@ -607,7 +621,7 @@ static void store_label_in_code_section (struct label *label) } #ifdef LINUX -static void store_pc_rel_got_label_in_code_section (struct label *label) +static void store_pc_rel_got_or_plt_label_in_code_section (struct label *label,int relocation_kind) { struct relocation *new_relocation; @@ -620,11 +634,16 @@ static void store_pc_rel_got_label_in_code_section (struct label *label) new_relocation->relocation_label=label; new_relocation->relocation_offset=CURRENT_CODE_OFFSET-4; - new_relocation->relocation_kind=GOT_PC_RELATIVE_RELOCATION; + new_relocation->relocation_kind=relocation_kind; # ifdef ELF_RELA new_relocation->relocation_addend=0; # endif } + +static void store_pc_rel_got_label_in_code_section (struct label *label) +{ + return store_pc_rel_got_or_plt_label_in_code_section (label,GOT_PC_RELATIVE_RELOCATION); +} #endif #ifdef ELF_RELA @@ -854,7 +873,16 @@ static void as_move_d_r (LABEL *label,int arity,int reg1) reg1_n=reg_num (reg1); - store_c (0x48 | ((reg1_n & 8)>>1)); + store_c (0x48 | ((reg1_n & 8)>>1)); +#ifdef LINUX + if (pic_flag && label->label_flags & USE_GOT_LABEL && arity==0){ + store_c (0x8b); /* movq */ + store_c (5 | ((reg1_n & 7)<<3)); + store_l (0); + store_pc_rel_got_label_in_code_section (label); + return; + } +#endif store_c (0x8d); /* lea */ store_c (5 | ((reg1_n & 7)<<3)); #ifdef ELF_RELA @@ -2415,10 +2443,24 @@ static void as_jmp_instruction (struct instruction *instruction) { switch (instruction->instruction_parameters[0].parameter_type){ case P_LABEL: + { + LABEL *label; + + label = instruction->instruction_parameters[0].parameter_data.l; +#ifdef LINUX + if (pic_flag && label->label_flags & USE_GOT_LABEL){ + store_c (0xff); + store_c (0x25); + store_l (0); + store_pc_rel_got_label_in_code_section (label); + return; + } +#endif store_c (0351); store_l (0); - as_branch_label (instruction->instruction_parameters[0].parameter_data.l,JUMP_RELOCATION); + as_branch_label (label,JUMP_RELOCATION); break; + } case P_INDIRECT: #ifndef MACH_O64 if ( @@ -2516,10 +2558,30 @@ static void as_jsr_instruction (struct instruction *instruction) { switch (instruction->instruction_parameters[0].parameter_type){ case P_LABEL: + { + LABEL *label; + + label = instruction->instruction_parameters[0].parameter_data.l; +#ifdef LINUX + if (pic_flag){ + if (label->label_flags & USE_GOT_LABEL){ + store_c (0xff); + store_c (0x15); + store_l (0); + store_pc_rel_got_label_in_code_section (label); + } else if (label->label_flags & USE_PLT_LABEL){ + store_c (0350); + store_l (0); + store_pc_rel_got_or_plt_label_in_code_section (label,PLT_PC_RELATIVE_RELOCATION); + } + return; + } +#endif store_c (0350); store_l (0); - as_branch_label (instruction->instruction_parameters[0].parameter_data.l,CALL_RELOCATION); + as_branch_label (label,CALL_RELOCATION); break; + } case P_INDIRECT: #ifndef MACH_O64 if ( @@ -2555,10 +2617,39 @@ static void as_jsr_instruction (struct instruction *instruction) static void as_branch_instruction (struct instruction *instruction,int condition_code) { + LABEL *label; + + label = instruction->instruction_parameters[0].parameter_data.l; + +#ifdef LINUX + if (pic_flag && label->label_flags & USE_GOT_LABEL){ + if (label->label_flags & HAS_GOT_JUMP_LABEL){ + label = label->label_got_jump_label; + } else { + struct got_jump *new_got_jump; + + new_got_jump=allocate_memory_from_heap (sizeof (struct got_jump)); + new_got_jump->gj_next=NULL; + + new_got_jump->gj_got_label = label; + + if (first_got_jump!=NULL) + last_got_jump->gj_next=new_got_jump; + else + first_got_jump=new_got_jump; + last_got_jump=new_got_jump; + + label->label_got_jump_label = &new_got_jump->gj_label; + label->label_flags |= HAS_GOT_JUMP_LABEL; + + label = &new_got_jump->gj_label; + } + } +#endif store_c (017); store_c (0200 | condition_code); store_l (0); - as_branch_label (instruction->instruction_parameters[0].parameter_data.l,BRANCH_RELOCATION); + as_branch_label (label,BRANCH_RELOCATION); } static void as_move_r_r (int reg1,int reg2) @@ -4247,50 +4338,67 @@ static void as_set_float_condition_instruction (struct instruction *instruction, store_c (0300 | ((r_n & 7)<<3) | (r_n & 7)); } -void define_data_label (LABEL *label) +static void create_new_data_object_label (LABEL *label) { - label->label_id=DATA_LABEL_ID; -#ifdef FUNCTION_LEVEL_LINKING - label->label_object_label=data_object_label; -#endif - label->label_offset=CURRENT_DATA_OFFSET; - - if (label->label_flags & EXPORT_LABEL){ - struct object_label *new_object_label; - int string_length; - - new_object_label=fast_memory_allocate_type (struct object_label); - *last_object_label_l=new_object_label; - last_object_label_l=&new_object_label->next; - new_object_label->next=NULL; - - new_object_label->object_label_label=label; + struct object_label *new_object_label; + int string_length; + + new_object_label=fast_memory_allocate_type (struct object_label); + *last_object_label_l=new_object_label; + last_object_label_l=&new_object_label->next; + new_object_label->next=NULL; + + new_object_label->object_label_label=label; #if defined (RELOCATIONS_RELATIVE_TO_EXPORTED_DATA_LABEL) && defined (FUNCTION_LEVEL_LINKING) - new_object_label->object_label_number = n_object_labels; + new_object_label->object_label_number = n_object_labels; #endif - ++n_object_labels; + ++n_object_labels; - string_length=strlen (label->label_name); + string_length=strlen (label->label_name); #ifndef ELF - if (string_length<8) - new_object_label->object_label_string_offset=0; - else + if (string_length<8) + new_object_label->object_label_string_offset=0; + else #endif - { - new_object_label->object_label_string_offset=string_table_offset; - string_table_offset+=string_length+1; - } + { + new_object_label->object_label_string_offset=string_table_offset; + string_table_offset+=string_length+1; + } #if defined (RELOCATIONS_RELATIVE_TO_EXPORTED_DATA_LABEL) && defined (FUNCTION_LEVEL_LINKING) - label->label_object_label=new_object_label; - new_object_label->object_label_section_n = data_object_label->object_label_section_n; + label->label_object_label=new_object_label; + new_object_label->object_label_section_n = data_object_label->object_label_section_n; #endif - new_object_label->object_label_kind=EXPORTED_DATA_LABEL; - } + new_object_label->object_label_kind=EXPORTED_DATA_LABEL; +} + +void define_data_label (LABEL *label) +{ + label->label_id=DATA_LABEL_ID; +#ifdef FUNCTION_LEVEL_LINKING + label->label_object_label=data_object_label; +#endif + label->label_offset=CURRENT_DATA_OFFSET; + + if (label->label_flags & EXPORT_LABEL) + create_new_data_object_label (label); } +#ifdef LINUX +void define_exported_data_label_with_offset (LABEL *label,int offset)\ +{ + label->label_id=DATA_LABEL_ID; +#ifdef FUNCTION_LEVEL_LINKING + label->label_object_label=data_object_label; +#endif + label->label_offset=CURRENT_DATA_OFFSET+offset; + + create_new_data_object_label (label); +} +#endif + void store_descriptor_string_in_data_section (char *string,int length,LABEL *string_label) { unsigned char *string_p; @@ -4799,15 +4907,42 @@ static void as_call_and_jump (struct call_and_jump *call_and_jump) #endif call_and_jump->cj_label.label_offset=CURRENT_CODE_OFFSET; +#ifdef LINUX + if (rts_got_flag){ + store_c (0xff); /* call */ + store_c (0x15); + store_l (0); + store_pc_rel_got_label_in_code_section (call_and_jump->cj_call_label); + } else +#endif + { store_c (0350); /* call */ store_l (0); as_branch_label (call_and_jump->cj_call_label,CALL_RELOCATION); + } store_c (0351); /* jmp */ store_l (0); as_branch_label (&call_and_jump->cj_jump,JUMP_RELOCATION); } +#ifdef LINUX +static void as_got_jump (struct got_jump *got_jump) +{ + got_jump->gj_label.label_flags=0; + got_jump->gj_label.label_id=TEXT_LABEL_ID; +#ifdef FUNCTION_LEVEL_LINKING + got_jump->gj_label.label_object_label=code_object_label; +#endif + got_jump->gj_label.label_offset=CURRENT_CODE_OFFSET; + + store_c (0xff); /* jmp */ + store_c (0x25); + store_l (0); + store_pc_rel_got_label_in_code_section (got_jump->gj_got_label); +} +#endif + static void as_check_stack (struct basic_block *block) { if (block->block_a_stack_check_size>0){ @@ -4878,7 +5013,22 @@ static void as_apply_update_entry (struct basic_block *block) store_c (0x90); store_c (0x90); store_c (0x90); + + store_c (0x90); } else { +#ifdef LINUX + if (rts_got_flag){ + store_c (0xff); /* call */ + store_c (0x15); + store_l (0); + store_pc_rel_got_label_in_code_section (add_empty_node_labels[block->block_n_node_arguments+200]); + + store_c (0351); /* jmp */ + store_l (0); + as_branch_label (block->block_ea_label,JUMP_RELOCATION); + } else +#endif + { store_c (0350); /* call */ store_l (0); as_branch_label (add_empty_node_labels[block->block_n_node_arguments+200],CALL_RELOCATION); @@ -4886,10 +5036,12 @@ static void as_apply_update_entry (struct basic_block *block) store_c (0351); /* jmp */ store_l (0); as_branch_label (block->block_ea_label,JUMP_RELOCATION); + + store_c (0x90); + } } store_c (0x90); - store_c (0x90); } #endif @@ -5019,6 +5171,21 @@ static void write_code (void) if (n_node_arguments>=0 && block->block_ea_label!=eval_fill_label){ if (!block->block_profile){ #ifdef LINUX + if (rts_got_flag){ + store_c (0xff); /* call */ + store_c (0x15); + store_l (0); + store_pc_rel_got_label_in_code_section (eval_upd_labels[n_node_arguments]); + + store_c (0351); + store_l (0); + store_relative_to_next_byte_label_offset_in_code_section (block->block_ea_label); + + store_c (0x90); + } else +#endif + { +#ifdef LINUX if (pic_flag) as_move_d_r (block->block_ea_label,0,REGISTER_A4); else @@ -5028,6 +5195,7 @@ static void write_code (void) store_c (0351); store_l (0); as_branch_label (eval_upd_labels[n_node_arguments],JUMP_RELOCATION); + } } else { as_move_l_r (block->block_profile_function_label,REGISTER_A4); @@ -5115,6 +5283,19 @@ static void write_code (void) #endif as_call_and_jump (call_and_jump); } + +#ifdef LINUX + { + struct got_jump *got_jump; + + for_l (got_jump,first_got_jump,gj_next){ +# ifdef FUNCTION_LEVEL_LINKING + as_new_code_module(); +# endif + as_got_jump (got_jump); + } + } +#endif } static void write_string_8 (char *string) @@ -5955,6 +6136,7 @@ static int search_short_branches (void) case BRANCH_SKIP_BRANCH_RELOCATION: #ifdef LINUX case GOT_PC_RELATIVE_RELOCATION: + case PLT_PC_RELATIVE_RELOCATION: #endif break; case SHORT_BRANCH_RELOCATION: @@ -6125,6 +6307,29 @@ static void adjust_label_offsets (void) relocation=calculate_new_label_offset (&call_and_jump->cj_label.label_offset,&offset_difference,&new_offset_difference,relocation); } + +#ifdef LINUX + { + struct got_jump *got_jump; + + for_l (got_jump,first_got_jump,gj_next){ +# ifdef FUNCTION_LEVEL_LINKING + while (object_label!=NULL){ + if (object_label->object_label_kind==CODE_CONTROL_SECTION){ + if (object_label->object_label_offset!=got_jump->gj_label.label_offset) + break; + + relocation=calculate_new_label_offset + (&object_label->object_label_offset,&offset_difference,&new_offset_difference,relocation); + } + object_label=object_label->next; + } +# endif + relocation=calculate_new_label_offset + (&got_jump->gj_label.label_offset,&offset_difference,&new_offset_difference,relocation); + } + } +#endif #ifdef FUNCTION_LEVEL_LINKING if (object_label!=NULL) @@ -6185,6 +6390,7 @@ static void relocate_short_branches_and_move_code (void) #endif #ifdef LINUX case GOT_PC_RELATIVE_RELOCATION: + case PLT_PC_RELATIVE_RELOCATION: #endif relocation->relocation_offset -= offset_difference; relocation_p=&relocation->next; @@ -6627,6 +6833,7 @@ static void relocate_code (void) #endif #ifdef LINUX case GOT_PC_RELATIVE_RELOCATION: + case PLT_PC_RELATIVE_RELOCATION: relocation_p=&relocation->next; instruction_offset=relocation->relocation_offset; @@ -6973,7 +7180,7 @@ static void write_object_labels (void) write_l (object_label->object_label_string_offset); write_c (ELF32_ST_INFO (STB_GLOBAL,STT_NOTYPE)); # ifdef LINUX - if (pic_flag) + if (!rts_got_flag) write_c (STV_PROTECTED); else # endif @@ -7330,6 +7537,30 @@ static void write_code_relocations (void) # endif break; } + case PLT_PC_RELATIVE_RELOCATION: + { + struct label *label; + + label=relocation->relocation_label; +# ifdef FUNCTION_LEVEL_LINKING + if (label->label_id==-1) +# else + if (label->label_id<0) +# endif + internal_error_in_function ("write_code_relocations"); + + write_q (relocation->relocation_offset); + write_l (R_X86_64_PLT32); +# ifdef FUNCTION_LEVEL_LINKING + write_l (elf_label_number (label)); +# else + write_l (label->label_id); +# endif +# ifdef ELF_RELA + write_q (relocation->relocation_addend); +# endif + break; + } #endif default: internal_error_in_function ("write_code_relocations"); @@ -6,6 +6,9 @@ void define_external_label (int id,int flag,char label_name[]); void store_word_in_data_section (UWORD i); void store_long_word_in_data_section (ULONG i); void define_data_label (LABEL *label); +#ifdef LINUX +void define_exported_data_label_with_offset (LABEL *label,int offset); +#endif void store_label_in_data_section (LABEL *label); #if defined (MACH_O64) || defined (LINUX) void store_label_offset_in_data_section (LABEL *label); @@ -278,6 +278,9 @@ int no_time_profiling; LABEL *INT_label,*BOOL_label,*CHAR_label,*REAL_label; LABEL *_STRING__label,*_ARRAY__label; +#if defined (G_A64) && defined (LINUX) +LABEL *_STRING__0_label; +#endif static LABEL *FILE_label; @@ -407,6 +410,54 @@ LABEL *enter_label (char *label_name,int label_flags) return &new_label->label_node_label; } +#if defined (G_A64) && defined (LINUX) +LABEL *enter_label_with_extension (char *label_name,char *label_name_extension,int label_flags) +{ + struct label_node **label_p,*new_label; + int label_name_length; + char *label_name_with_extension; + + label_name_length=strlen (label_name); + + label_p=&labels; + while (*label_p!=NULL){ + struct label_node *label; + int r; + + label=*label_p; + r=strncmp (label_name,label->label_node_label.label_name,label_name_length); + if (r==0){ + r=strcmp (label_name_extension,label->label_node_label.label_name+label_name_length); + if (r==0){ + label->label_node_label.label_flags |= label_flags; + return &label->label_node_label; + } + } + if (r<0) + label_p=&label->label_node_left; + else + label_p=&label->label_node_right; + } + + new_label=fast_memory_allocate_type (struct label_node); + new_label->label_node_left=NULL; + new_label->label_node_right=NULL; + new_label->label_node_label.label_flags=label_flags; + new_label->label_node_label.label_number=0; + new_label->label_node_label.label_id=-1; + label_name_with_extension + =(char*)fast_memory_allocate (label_name_length+strlen (label_name_extension)+1); + strcpy (label_name_with_extension,label_name); + strcpy (label_name_with_extension+label_name_length,label_name_extension); + new_label->label_node_label.label_name=label_name_with_extension; + + new_label->label_node_label.label_last_lea_block=NULL; + + *label_p=new_label; + return &new_label->label_node_label; +} +#endif + static int next_label; #define LTEXT 0 @@ -739,6 +790,13 @@ static void define_eval_upd_label_n (int arity) { char eval_upd_label_name[32]; +#if defined (G_A64) && defined (LINUX) + if (rts_got_flag){ + sprintf (eval_upd_label_name,"eval_upd_%d_",arity); + eval_upd_labels[arity]=enter_label (eval_upd_label_name,IMPORT_LABEL | USE_GOT_LABEL); + return; + } +#endif sprintf (eval_upd_label_name,"eval_upd_%d",arity); eval_upd_labels[arity]=enter_label (eval_upd_label_name,IMPORT_LABEL); } @@ -799,6 +857,16 @@ void code_build (char descriptor_name[],int arity,char *code_name) } } +#if defined (G_A64) && defined (LINUX) +static LABEL *enter_got_label (char *descriptor_name,int arity,int label_flags) +{ + static char arity_extension[24]; + + sprintf (arity_extension,"_%d",arity); + return enter_label_with_extension (descriptor_name,arity_extension,label_flags | USE_GOT_LABEL); +} +#endif + void code_buildh (char descriptor_name[],int arity) { INSTRUCTION_GRAPH graph_2,graph_3,graph_4,graph_5,graph_6; @@ -807,6 +875,12 @@ void code_buildh (char descriptor_name[],int arity) descriptor_label=enter_label (descriptor_name,DATA_LABEL); if (!parallel_flag && arity==0){ +#if defined (G_A64) && defined (LINUX) + if (pic_flag && descriptor_label->label_flags & USE_GOT_LABEL){ + descriptor_label=enter_label_with_extension (descriptor_name,"_Z",DATA_LABEL | USE_GOT_LABEL); + graph_4=g_lea (descriptor_label); + } else +#endif graph_4=g_lea_i (descriptor_label,ARITY_0_DESCRIPTOR_OFFSET+NODE_POINTER_OFFSET); s_push_a (graph_4); return; @@ -818,6 +892,12 @@ void code_buildh (char descriptor_name[],int arity) { graph_2=descriptor_label->label_last_lea; } else { +#if defined (G_A64) && defined (LINUX) + if (pic_flag && descriptor_label->label_flags & USE_GOT_LABEL){ + descriptor_label=enter_got_label (descriptor_name,arity,DATA_LABEL); + graph_2=g_lea (descriptor_label); + } else +#endif graph_2=g_load_des_i (descriptor_label,arity); if (!parallel_flag ){ @@ -872,6 +952,12 @@ void code_build_r (char descriptor_name[],int a_size,int b_size,int a_offset,int if (!parallel_flag && descriptor_label->label_last_lea_block==last_block) graph_2=descriptor_label->label_last_lea; else { +#if defined (G_A64) && defined (LINUX) + if (pic_flag && descriptor_label->label_flags & USE_GOT_LABEL){ + descriptor_label=enter_got_label (descriptor_name,0,DATA_LABEL); + graph_2=g_lea (descriptor_label); + } else +#endif graph_2=g_load_des_i (descriptor_label,0); if (!parallel_flag ){ @@ -992,6 +1078,13 @@ void code_build_u (char descriptor_name[],int a_size,int b_size,char *code_name) static INSTRUCTION_GRAPH g_BOOL_label (void) { +#if defined (G_A64) && defined (LINUX) + if (rts_got_flag){ + if (BOOL_label==NULL) + BOOL_label=enter_label ("BOOL_0",IMPORT_LABEL | DATA_LABEL | USE_GOT_LABEL); + return g_lea (BOOL_label); + } +#endif if (BOOL_label==NULL) BOOL_label=enter_label ("BOOL",IMPORT_LABEL | DATA_LABEL); return g_load_des_i (BOOL_label,0); @@ -999,6 +1092,13 @@ static INSTRUCTION_GRAPH g_BOOL_label (void) static INSTRUCTION_GRAPH g_FILE_label (void) { +#if defined (G_A64) && defined (LINUX) + if (rts_got_flag){ + if (FILE_label==NULL) + FILE_label=enter_label ("FILE_0",IMPORT_LABEL | DATA_LABEL | USE_GOT_LABEL); + return g_lea (FILE_label); + } +#endif if (FILE_label==NULL) FILE_label=enter_label ("FILE",IMPORT_LABEL | DATA_LABEL); return g_load_des_i (FILE_label,0); @@ -1086,10 +1186,22 @@ void code_buildC (int value) INSTRUCTION_GRAPH graph_2,graph_3,graph_4; if (!parallel_flag){ +#if defined (G_A64) && defined (LINUX) + if (rts_got_flag){ + LABEL *static_characters_n_label; + static char static_characters_n_s[40]; + + sprintf (static_characters_n_s,"static_characters_%d",(int)value); + static_characters_n_label=enter_label (static_characters_n_s,IMPORT_LABEL | DATA_LABEL | USE_GOT_LABEL); + graph_4=g_lea (static_characters_n_label); + } else +#endif + { if (static_characters_label==NULL) static_characters_label=enter_label ("static_characters",IMPORT_LABEL | DATA_LABEL); graph_4=g_lea_i (static_characters_label,(value<<(1+STACK_ELEMENT_LOG_SIZE))+NODE_POINTER_OFFSET); + } s_push_a (graph_4); return; } @@ -1145,14 +1257,22 @@ static INSTRUCTION_GRAPH int_descriptor_graph (void) if (!parallel_flag && last_INT_descriptor_block==last_block) graph=last_INT_descriptor_graph; else { +#if defined (G_A64) && defined (LINUX) + if (rts_got_flag){ + if (INT_label==NULL) + INT_label=enter_label ("dINT_0",IMPORT_LABEL | DATA_LABEL | USE_GOT_LABEL); + graph=g_lea (INT_label); + } else +#endif + { if (INT_label==NULL) #ifdef G_AI64 INT_label=enter_label ("dINT",IMPORT_LABEL | DATA_LABEL); #else INT_label=enter_label ("INT",IMPORT_LABEL | DATA_LABEL); #endif - graph=g_load_des_i (INT_label,0); + } if (!parallel_flag){ last_INT_descriptor_graph=graph; @@ -1172,10 +1292,23 @@ void code_buildI (CleanInt value) #else if (!parallel_flag && (uint_64)value<(uint_64)33){ #endif +#if defined (G_A64) && defined (LINUX) + if (rts_got_flag){ + LABEL *small_integers_n_label; + static char small_integers_n_s[40]; + + sprintf (small_integers_n_s,"small_integers_%d",(int)value); + small_integers_n_label=enter_label (small_integers_n_s,IMPORT_LABEL | DATA_LABEL | USE_GOT_LABEL); + graph_5=g_lea (small_integers_n_label); + } else +#endif + { if (small_integers_label==NULL) small_integers_label=enter_label ("small_integers",IMPORT_LABEL | DATA_LABEL); graph_5=g_lea_i (small_integers_label,(value<<(STACK_ELEMENT_LOG_SIZE+1))+NODE_POINTER_OFFSET); + } + s_push_a (graph_5); return; } @@ -1332,10 +1465,19 @@ void code_CtoAC (VOID) if (!parallel_flag && last__STRING__descriptor_block==last_block) graph_1=last__STRING__descriptor_graph; else { +#if defined (G_A64) && defined (LINUX) + if (rts_got_flag){ + if (_STRING__0_label==NULL) + _STRING__0_label=enter_label ("__STRING___0",IMPORT_LABEL | DATA_LABEL | USE_GOT_LABEL); + graph_1=g_lea (_STRING__0_label); + } else +#endif + { if (_STRING__label==NULL) _STRING__label=enter_label ("__STRING__",IMPORT_LABEL | DATA_LABEL); graph_1=g_load_des_i (_STRING__label,0); + } if (!parallel_flag){ last__STRING__descriptor_graph=graph_1; @@ -1359,10 +1501,20 @@ void code_CtoAC (VOID) s_push_a (graph_4); } +static LABEL *enter_rts_label (char *label_name) +{ + return enter_label (label_name, +#if defined (G_A64) && defined (LINUX) + rts_got_flag ? IMPORT_LABEL | USE_GOT_LABEL : IMPORT_LABEL); +#else + IMPORT_LABEL); +#endif +} + static void code_create_lazy_array (VOID) { if (create_array_label==NULL) - create_array_label=enter_label ("create_array",IMPORT_LABEL); + create_array_label=enter_rts_label ("create_array"); s_push_b (s_get_b (0)); s_put_b (1,NULL); @@ -1374,7 +1526,7 @@ static void code_create_lazy_array (VOID) static void code_create_arrayB (VOID) { if (create_arrayB_label==NULL) - create_arrayB_label=enter_label ("create_arrayB",IMPORT_LABEL); + create_arrayB_label=enter_rts_label ("create_arrayB"); s_push_b (s_get_b (0)); s_put_b (1,s_get_b (2)); @@ -1387,8 +1539,8 @@ static void code_create_arrayB (VOID) static void code_create_arrayC (VOID) { if (create_arrayC_label==NULL) - create_arrayC_label=enter_label ("create_arrayC",IMPORT_LABEL); - + create_arrayC_label=enter_rts_label ("create_arrayC"); + s_push_b (s_get_b (0)); s_put_b (1,s_get_b (2)); s_put_b (2,NULL); @@ -1399,15 +1551,25 @@ static void code_create_arrayC (VOID) INSTRUCTION_GRAPH g_create_unboxed_int_array (int n_elements) { - INSTRUCTION_GRAPH graph_1; + INSTRUCTION_GRAPH graph_1,graph_2; int n; graph_1=g_create_m (n_elements+3); +#if defined (G_A64) && defined (LINUX) + if (rts_got_flag){ + if (_ARRAY__label==NULL) + _ARRAY__label=enter_label ("__ARRAY__",IMPORT_LABEL | DATA_LABEL | USE_GOT_LABEL); + graph_2=g_lea (_ARRAY__label); + } else +#endif + { if (_ARRAY__label==NULL) _ARRAY__label=enter_label ("__ARRAY__",IMPORT_LABEL | DATA_LABEL); + graph_2=g_load_des_i (_ARRAY__label,0); + } - graph_1->instruction_parameters[0].p=g_load_des_i (_ARRAY__label,0);; + graph_1->instruction_parameters[0].p=graph_2; graph_1->instruction_parameters[1].p=g_load_i (n_elements); graph_1->instruction_parameters[2].p=int_descriptor_graph(); @@ -1436,7 +1598,7 @@ static void code_create_arrayI (VOID) s_push_a (graph_2); } else { if (create_arrayI_label==NULL) - create_arrayI_label=enter_label ("create_arrayI",IMPORT_LABEL); + create_arrayI_label=enter_rts_label ("create_arrayI"); s_push_b (graph_1); s_put_b (1,s_get_b (2)); @@ -1451,7 +1613,7 @@ static void code_create_arrayI (VOID) static void code_create_arrayI32 (VOID) { if (create_arrayI32_label==NULL) - create_arrayI32_label=enter_label ("create_arrayI32",IMPORT_LABEL); + create_arrayI32_label=enter_rts_label ("create_arrayI32"); s_push_b (s_get_b (0)); s_put_b (1,s_get_b (2)); @@ -1465,7 +1627,7 @@ static void code_create_arrayI32 (VOID) static void code_create_arrayR (VOID) { if (create_arrayR_label==NULL) - create_arrayR_label=enter_label ("create_arrayR",IMPORT_LABEL); + create_arrayR_label=enter_rts_label ("create_arrayR"); #ifdef M68000 if (!mc68881_flag){ @@ -1515,7 +1677,7 @@ static void code_create_arrayR (VOID) static void code_create_arrayR32 (VOID) { if (create_arrayR32_label==NULL) - create_arrayR32_label=enter_label ("create_arrayR32",IMPORT_LABEL); + create_arrayR32_label=enter_rts_label ("create_arrayR32"); s_push_b (s_get_b (0)); s_put_b (1,s_get_b (2)); @@ -1530,14 +1692,21 @@ static void code_create_r_array (char element_descriptor[],int a_size,int b_size { INSTRUCTION_GRAPH graph_1,graph_2,graph_3,graph_4; LABEL *descriptor; - - descriptor=enter_label (element_descriptor,DATA_LABEL); - + if (create_r_array_label==NULL) - create_r_array_label=enter_label ("create_R_array",IMPORT_LABEL); + create_r_array_label=enter_rts_label ("create_R_array"); graph_1=s_pop_b(); + + descriptor=enter_label (element_descriptor,DATA_LABEL); +#if defined (G_A64) && defined (LINUX) + if (pic_flag && descriptor->label_flags & USE_GOT_LABEL){ + descriptor=enter_got_label (element_descriptor,0,DATA_LABEL); + graph_2=g_lea (descriptor); + } else +#endif graph_2=g_load_des_i (descriptor,0); + graph_3=g_load_i (a_size+b_size); graph_4=g_load_i (a_size); @@ -1690,11 +1859,19 @@ static void code_create_lazy_array_ (VOID) INSTRUCTION_GRAPH graph_1; LABEL *nil_label; +#if defined (G_A64) && defined (LINUX) + if (rts_got_flag){ + nil_label=enter_label ("__Nil_Z",DATA_LABEL | USE_GOT_LABEL); + graph_1=g_lea (nil_label); + } else +#endif + { nil_label=enter_label ("__Nil",DATA_LABEL); if (!parallel_flag) graph_1=g_lea_i (nil_label,ARITY_0_DESCRIPTOR_OFFSET+NODE_POINTER_OFFSET); else graph_1=g_create_1 (g_load_des_i (nil_label,0)); + } s_push_a (graph_1); code_create_lazy_array(); @@ -1708,7 +1885,7 @@ void code_create_array_ (char element_descriptor[],int a_size,int b_size) element_descriptor[4]=='\0') { if (create_arrayB__label==NULL) - create_arrayB__label=enter_label ("_create_arrayB",IMPORT_LABEL); + create_arrayB__label=enter_rts_label ("_create_arrayB"); s_push_b (s_get_b (0)); s_put_b (1,NULL); @@ -1723,7 +1900,7 @@ void code_create_array_ (char element_descriptor[],int a_size,int b_size) element_descriptor[4]=='\0') { if (create_arrayC__label==NULL) - create_arrayC__label=enter_label ("_create_arrayC",IMPORT_LABEL); + create_arrayC__label=enter_rts_label ("_create_arrayC"); s_push_b (s_get_b (0)); s_put_b (1,NULL); @@ -1749,7 +1926,7 @@ void code_create_array_ (char element_descriptor[],int a_size,int b_size) s_push_a (graph_2); } else { if (create_arrayI__label==NULL) - create_arrayI__label=enter_label ("_create_arrayI",IMPORT_LABEL); + create_arrayI__label=enter_rts_label ("_create_arrayI"); s_push_b (graph_1); s_put_b (1,NULL); @@ -1763,7 +1940,7 @@ void code_create_array_ (char element_descriptor[],int a_size,int b_size) case 'P': if (is__rocid (element_descriptor)){ if (create_arrayI__label==NULL) - create_arrayI__label=enter_label ("_create_arrayI",IMPORT_LABEL); + create_arrayI__label=enter_rts_label ("_create_arrayI"); s_push_b (s_get_b (0)); s_put_b (1,NULL); @@ -1778,7 +1955,7 @@ void code_create_array_ (char element_descriptor[],int a_size,int b_size) element_descriptor[4]=='\0') { if (create_arrayR__label==NULL) - create_arrayR__label=enter_label ("_create_arrayR",IMPORT_LABEL); + create_arrayR__label=enter_rts_label ("_create_arrayR"); s_push_b (s_get_b (0)); s_put_b (1,NULL); @@ -1826,22 +2003,37 @@ void code_create_array_ (char element_descriptor[],int a_size,int b_size) INSTRUCTION_GRAPH graph_1; LABEL *nil_label; +#if defined (G_A64) && defined (LINUX) + if (rts_got_flag){ + nil_label=enter_label ("__Nil_Z",DATA_LABEL | USE_GOT_LABEL); + graph_1=g_lea (nil_label); + } else +#endif + { nil_label=enter_label ("__Nil",DATA_LABEL); if (!parallel_flag) graph_1=g_lea_i (nil_label,ARITY_0_DESCRIPTOR_OFFSET+NODE_POINTER_OFFSET); else graph_1=g_create_1 (g_load_des_i (nil_label,0)); + } s_push_a (graph_1); } - - descriptor=enter_label (element_descriptor,DATA_LABEL); - + if (create_r_array__label==NULL) - create_r_array__label=enter_label ("_create_r_array",IMPORT_LABEL); + create_r_array__label=enter_rts_label ("_create_r_array"); graph_1=s_pop_b(); + + descriptor=enter_label (element_descriptor,DATA_LABEL); +#if defined (G_A64) && defined (LINUX) + if (pic_flag && descriptor->label_flags & USE_GOT_LABEL){ + descriptor=enter_got_label (element_descriptor,0,DATA_LABEL); + graph_2=g_lea (descriptor); + } else +#endif graph_2=g_load_des_i (descriptor,0); + graph_3=g_load_i (a_size+b_size); graph_4=g_load_i (a_size); @@ -2283,7 +2475,14 @@ void code_eqD_b (char descriptor_name[],int arity) graph_1=s_get_b (0); +#if defined (G_A64) && defined (LINUX) + if (pic_flag && descriptor->label_flags & USE_GOT_LABEL){ + descriptor=enter_got_label (descriptor_name,arity,DATA_LABEL); + graph_2=g_lea (descriptor); + } else +#endif graph_2=g_load_des_i (descriptor,arity); + graph_3=g_cmp_eq (graph_2,graph_1); s_push_b (graph_3); @@ -2462,7 +2661,11 @@ void code_eqAC_a (char *string,int string_length) LABEL *string_label; if (equal_string_label==NULL) - equal_string_label=enter_label ("eqAC",IMPORT_LABEL); + equal_string_label=enter_label ("eqAC", +#if defined (G_A64) && defined (LINUX) + rts_got_flag ? (USE_GOT_LABEL | IMPORT_LABEL) : +#endif + IMPORT_LABEL); string_label=w_code_length_and_string (string,string_length); @@ -2494,7 +2697,14 @@ void code_eq_desc (char descriptor_name[],int arity,int a_offset) graph_2=g_load_des_id (DESCRIPTOR_OFFSET,graph_1); #endif +#if defined (G_A64) && defined (LINUX) + if (pic_flag && descriptor->label_flags & USE_GOT_LABEL){ + descriptor=enter_got_label (descriptor_name,arity,DATA_LABEL); + graph_3=g_lea (descriptor); + } else +#endif graph_3=g_load_des_i (descriptor,arity); + graph_4=g_cmp_eq (graph_3,graph_2); s_push_b (graph_4); @@ -2624,6 +2834,14 @@ void code_fill_r (char descriptor_name[],int a_size,int b_size,int root_offset,i if (!parallel_flag && descriptor_label->label_last_lea_block==last_block) graph_2=descriptor_label->label_last_lea; else { +#if defined (G_A64) && defined (LINUX) + if (pic_flag && descriptor_label->label_flags & USE_GOT_LABEL){ + LABEL *descriptor_label_0; + + descriptor_label_0=enter_got_label (descriptor_name,0,DATA_LABEL); + graph_2=g_lea (descriptor_label_0); + } else +#endif graph_2=g_load_des_i (descriptor_label,0); if (!parallel_flag ){ @@ -2953,6 +3171,12 @@ void code_fillh (char descriptor_name[],int arity,int a_offset) { graph_2=descriptor_label->label_last_lea; } else { +#if defined (G_A64) && defined (LINUX) + if (pic_flag && descriptor_label->label_flags & USE_GOT_LABEL){ + descriptor_label=enter_got_label (descriptor_name,arity,DATA_LABEL); + graph_2=g_lea (descriptor_label); + } else +#endif graph_2=g_load_des_i (descriptor_label,arity); if (!parallel_flag ){ @@ -3508,7 +3732,11 @@ void code_fillcaf (char *label_name,int a_stack_size,int b_stack_size) INSTRUCTION_GRAPH graph_5,graph_6,graph_7,graph_8; LABEL *caf_listp_label; - caf_listp_label=enter_label ("caf_listp",DATA_LABEL | IMPORT_LABEL); + caf_listp_label=enter_label ("caf_listp", +#if defined (G_A64) && defined (LINUX) + rts_got_flag ? USE_GOT_LABEL | DATA_LABEL | IMPORT_LABEL : +#endif + DATA_LABEL | IMPORT_LABEL); graph_5=g_lea (caf_listp_label); graph_6=g_sub (g_load_i (STACK_ELEMENT_SIZE),g_load_id (0,graph_5)); @@ -3751,7 +3979,7 @@ void code_gtU (VOID) void code_halt (VOID) { if (halt_label==NULL) - halt_label=enter_label ("halt",IMPORT_LABEL); + halt_label=enter_rts_label ("halt"); end_basic_block_with_registers (0,0,e_vector); @@ -3861,6 +4089,8 @@ static struct basic_block *profile_function_block; int profile_flag=PROFILE_NORMAL; +static void code_jmp_label (LABEL *label); + static void code_jmp_ap_ (int n_apply_args) { if (n_apply_args==1){ @@ -3927,98 +4157,109 @@ static void code_jmp_ap_ (int n_apply_args) begin_new_basic_block(); } else { char ap_label_name[32]; + LABEL *label; sprintf (ap_label_name,"ap_%d",n_apply_args); - code_jmp (ap_label_name); + label=enter_label (ap_label_name, +#if defined (G_A64) && defined (LINUX) + rts_got_flag ? USE_GOT_LABEL : +#endif + 0); + code_jmp_label (label); } } -void code_jmp (char label_name[]) +static void code_jmp_label (LABEL *label) { - if (!strcmp (label_name,"e__system__sAP")) - code_jmp_ap_(1); - else { - LABEL *label; - int a_stack_size,b_stack_size,n_a_and_f_registers; - ULONG *vector; + int a_stack_size,b_stack_size,n_a_and_f_registers; + ULONG *vector; - label=enter_label (label_name,0); + if (demand_flag){ + a_stack_size=demanded_a_stack_size; + b_stack_size=demanded_b_stack_size; + vector=demanded_vector; - if (demand_flag){ - a_stack_size=demanded_a_stack_size; - b_stack_size=demanded_b_stack_size; - vector=demanded_vector; - - end_basic_block_with_registers (a_stack_size,b_stack_size,vector); - } else { - generate_code_for_previous_blocks (1); - if (!(label->label_flags & REGISTERS_ALLOCATED)){ - label->label_a_stack_size=get_a_stack_size(); - label->label_vector=&label->label_small_vector; - label->label_b_stack_size=get_b_stack_size (&label->label_vector); - label->label_flags |= REGISTERS_ALLOCATED; - } - - a_stack_size=label->label_a_stack_size; - b_stack_size=label->label_b_stack_size; - vector=label->label_vector; - - end_stack_elements (a_stack_size,b_stack_size,vector); - linearize_stack_graphs(); - adjust_stack_pointers(); + end_basic_block_with_registers (a_stack_size,b_stack_size,vector); + } else { + generate_code_for_previous_blocks (1); + if (!(label->label_flags & REGISTERS_ALLOCATED)){ + label->label_a_stack_size=get_a_stack_size(); + label->label_vector=&label->label_small_vector; + label->label_b_stack_size=get_b_stack_size (&label->label_vector); + label->label_flags |= REGISTERS_ALLOCATED; } - - n_a_and_f_registers=0; - if (mc68881_flag){ - int parameter_n; + a_stack_size=label->label_a_stack_size; + b_stack_size=label->label_b_stack_size; + vector=label->label_vector; + + end_stack_elements (a_stack_size,b_stack_size,vector); + linearize_stack_graphs(); + adjust_stack_pointers(); + } + + n_a_and_f_registers=0; + + if (mc68881_flag){ + int parameter_n; - for (parameter_n=0; parameter_n<b_stack_size; ++parameter_n) - if (test_bit (vector,parameter_n)) - if (n_a_and_f_registers<N_FLOAT_PARAMETER_REGISTERS){ - ++n_a_and_f_registers; + for (parameter_n=0; parameter_n<b_stack_size; ++parameter_n) + if (test_bit (vector,parameter_n)) + if (n_a_and_f_registers<N_FLOAT_PARAMETER_REGISTERS){ + ++n_a_and_f_registers; #ifndef G_A64 - ++parameter_n; + ++parameter_n; #endif - } else - break; - } + } else + break; + } - n_a_and_f_registers+= - (a_stack_size<=N_ADDRESS_PARAMETER_REGISTERS) ? (a_stack_size<<4) : (N_ADDRESS_PARAMETER_REGISTERS<<4); + n_a_and_f_registers+= + (a_stack_size<=N_ADDRESS_PARAMETER_REGISTERS) ? (a_stack_size<<4) : (N_ADDRESS_PARAMETER_REGISTERS<<4); #ifdef PROFILE - if (profile_function_label!=NULL && profile_flag!=PROFILE_NOT && demand_flag){ - int tail_call_profile; + if (profile_function_label!=NULL && profile_flag!=PROFILE_NOT && demand_flag){ + int tail_call_profile; + + if (profile_flag==PROFILE_TAIL) + tail_call_profile=1; + else { + struct block_label *profile_block_label; - if (profile_flag==PROFILE_TAIL) - tail_call_profile=1; - else { - struct block_label *profile_block_label; - - tail_call_profile=0; - - if (profile_function_block!=NULL){ - for_l (profile_block_label,profile_function_block->block_labels,block_label_next) - if (profile_block_label->block_label_label==label) - tail_call_profile=1; - } - } + tail_call_profile=0; - if (! tail_call_profile) - i_jmp_l_profile (label,0); - else - i_jmp_l_profile (label,profile_offset); - } else + if (profile_function_block!=NULL){ + for_l (profile_block_label,profile_function_block->block_labels,block_label_next) + if (profile_block_label->block_label_label==label) + tail_call_profile=1; + } + } + + if (! tail_call_profile) + i_jmp_l_profile (label,0); + else + i_jmp_l_profile (label,profile_offset); + } else #endif - i_jmp_l (label,n_a_and_f_registers); + i_jmp_l (label,n_a_and_f_registers); - profile_flag=PROFILE_NORMAL; - demand_flag=0; - - reachable=0; - - begin_new_basic_block(); + profile_flag=PROFILE_NORMAL; + demand_flag=0; + + reachable=0; + + begin_new_basic_block(); +} + +void code_jmp (char label_name[]) +{ + if (!strcmp (label_name,"e__system__sAP")) + code_jmp_ap_(1); + else { + LABEL *label; + + label=enter_label (label_name,0); + code_jmp_label (label); } } @@ -4389,6 +4630,8 @@ static int too_many_b_stack_parameters_for_registers (int b_stack_size,int n_dat } #endif +static void code_jsr_label (LABEL *label); + static void code_jsr_ap_ (int n_apply_args) { INSTRUCTION_GRAPH graph_1,graph_2,graph_3,graph_4,graph_5; @@ -4426,62 +4669,85 @@ static void code_jsr_ap_ (int n_apply_args) init_a_stack (1); } else { char ap_label_name[32]; + LABEL *label; sprintf (ap_label_name,"ap_%d",n_apply_args); - code_jsr (ap_label_name); + label=enter_label (ap_label_name, +#if defined (G_A64) && defined (LINUX) + rts_got_flag ? USE_GOT_LABEL : +#endif + 0); + code_jsr_label (label); } } -void code_jsr (char label_name[]) +static void code_jsr_label (LABEL *label) { - if (!strcmp (label_name,"e__system__sAP")) - code_jsr_ap_ (1); - else { - LABEL *label; - INSTRUCTION_GRAPH graph; - int b_stack_size,n_data_parameter_registers; + INSTRUCTION_GRAPH graph; + int b_stack_size,n_data_parameter_registers; #if defined (M68000) || defined (I486) - LABEL *label_2; + LABEL *label_2; #endif - if (!demand_flag) - error ("Directive .d missing before jsr instruction"); - - label=enter_label (label_name,0); - - offered_after_jsr=1; - demand_flag=0; + if (!demand_flag) + error ("Directive .d missing before jsr instruction"); - n_data_parameter_registers=parallel_flag ? N_DATA_PARAMETER_REGISTERS-1 : N_DATA_PARAMETER_REGISTERS; + offered_after_jsr=1; + demand_flag=0; + + n_data_parameter_registers=parallel_flag ? N_DATA_PARAMETER_REGISTERS-1 : N_DATA_PARAMETER_REGISTERS; #ifdef MORE_PARAMETER_REGISTERS - if (demanded_a_stack_size<N_ADDRESS_PARAMETER_REGISTERS) - n_data_parameter_registers += N_ADDRESS_PARAMETER_REGISTERS-demanded_a_stack_size; + if (demanded_a_stack_size<N_ADDRESS_PARAMETER_REGISTERS) + n_data_parameter_registers += N_ADDRESS_PARAMETER_REGISTERS-demanded_a_stack_size; #endif - graph=NULL; + graph=NULL; - b_stack_size=demanded_b_stack_size; + b_stack_size=demanded_b_stack_size; #if defined (M68000) || defined (I486) - if (b_stack_size>n_data_parameter_registers || !mc68881_flag){ - if (too_many_b_stack_parameters_for_registers (b_stack_size,n_data_parameter_registers)){ - sprintf (eval_label_s,"e_%d",eval_label_number++); - label_2=enter_label (eval_label_s,LOCAL_LABEL); - graph=g_lea (label_2); - } + if (b_stack_size>n_data_parameter_registers || !mc68881_flag){ + if (too_many_b_stack_parameters_for_registers (b_stack_size,n_data_parameter_registers)){ + sprintf (eval_label_s,"e_%d",eval_label_number++); + label_2=enter_label (eval_label_s,LOCAL_LABEL); + graph=g_lea (label_2); } + } #endif - insert_graph_in_b_stack (graph,b_stack_size,demanded_vector); + insert_graph_in_b_stack (graph,b_stack_size,demanded_vector); - clear_bit (demanded_vector,b_stack_size); - ++b_stack_size; + clear_bit (demanded_vector,b_stack_size); + ++b_stack_size; - insert_basic_block (JSR_BLOCK,demanded_a_stack_size,b_stack_size,demanded_vector,label); + insert_basic_block (JSR_BLOCK,demanded_a_stack_size,b_stack_size,demanded_vector,label); #if defined (M68000) || defined (I486) - if (graph!=NULL) - define_label_in_block (label_2); + if (graph!=NULL) + define_label_in_block (label_2); #endif +} + +void code_jrsr (char label_name[]) +{ + LABEL *label; + + label=enter_label (label_name, +#if defined (G_A64) && defined (LINUX) + rts_got_flag ? USE_GOT_LABEL : +#endif + 0); + code_jsr_label (label); +} + +void code_jsr (char label_name[]) +{ + if (!strcmp (label_name,"e__system__sAP")) + code_jsr_ap_ (1); + else { + LABEL *label; + + label=enter_label (label_name,0); + code_jsr_label (label); } } @@ -5038,7 +5304,11 @@ void code_n (int number_of_arguments,char *descriptor_name,char *ea_label_name) if (ea_label_name!=NULL){ if (ea_label_name[0]=='_' && ea_label_name[1]=='_' && ea_label_name[2]=='\0'){ if (eval_fill_label==NULL) - eval_fill_label=enter_label ("eval_fill",IMPORT_LABEL); + eval_fill_label=enter_label ("eval_fill", +#if defined (G_A64) && defined (LINUX) + rts_got_flag ? (IMPORT_LABEL | USE_GOT_LABEL) : +#endif + IMPORT_LABEL); last_block->block_ea_label=eval_fill_label; } else { if (number_of_arguments<-2) @@ -5068,7 +5338,11 @@ void code_nu (int a_size,int b_size,char *descriptor_name,char *ea_label_name) if (ea_label_name!=NULL){ /* eval_upd not yet implemented */ if (eval_fill_label==NULL) - eval_fill_label=enter_label ("eval_fill",IMPORT_LABEL); + eval_fill_label=enter_label ("eval_fill", +#if defined (G_A64) && defined (LINUX) + rts_got_flag ? (IMPORT_LABEL | USE_GOT_LABEL) : +#endif + IMPORT_LABEL); last_block->block_ea_label=eval_fill_label; } else last_block->block_ea_label=NULL; @@ -5181,7 +5455,11 @@ void code_print (char *string,int length) #ifdef G_POWER print_label=enter_label ("print_",IMPORT_LABEL); #else - print_label=enter_label ("print",IMPORT_LABEL); + print_label=enter_label ("print", +# if defined (G_A64) && defined (LINUX) + rts_got_flag ? (USE_GOT_LABEL | IMPORT_LABEL) : +# endif + IMPORT_LABEL); #endif string_label=w_code_string (string,length); @@ -8930,6 +9208,23 @@ static void code_descriptor (char label_name[],char node_entry_label_name[],char #endif if (assembly_flag) w_as_define_label (label); + +#if defined (G_A64) && defined (LINUX) + if (pic_flag && label->label_flags & EXPORT_LABEL){ + int n; + + define_exported_data_label_with_offset + (enter_label_with_extension (label->label_name,"_Z",label->label_flags),ARITY_0_DESCRIPTOR_OFFSET); + + for (n=0; n<=arity; ++n){ + static char arity_extension[24]; + + sprintf (arity_extension,"_%d",n); + define_exported_data_label_with_offset + (enter_label_with_extension (label->label_name,arity_extension,label->label_flags),2+(n<<4)); + } + } +#endif } #ifdef NEW_DESCRIPTORS @@ -9306,6 +9601,11 @@ void code_record (char record_label_name[],char type[],int a_size,int b_size,cha if (assembly_flag) w_as_define_label (label); +#if defined (G_A64) && defined (LINUX) + if (pic_flag && label->label_flags & EXPORT_LABEL) + define_exported_data_label_with_offset (enter_label_with_extension (label->label_name,"_0",label->label_flags),2); +#endif + #ifdef GEN_OBJ store_2_words_in_data_section (a_size+b_size+256,a_size); #endif @@ -9386,7 +9686,12 @@ static int pic_sl_mod_import; void code_impdesc (char *label_name) { - enter_label (label_name,IMPORT_LABEL | DATA_LABEL); + enter_label (label_name, +#if defined (G_A64) && defined (LINUX) + !pic_sl_mod_import ? IMPORT_LABEL | DATA_LABEL | USE_GOT_LABEL : IMPORT_LABEL | DATA_LABEL); +#else + IMPORT_LABEL | DATA_LABEL); +#endif } void code_implab_node_entry (char *label_name,char *ea_label_name) @@ -9394,11 +9699,20 @@ void code_implab_node_entry (char *label_name,char *ea_label_name) if (ea_label_name!=NULL){ LABEL *ea_label,*node_label; - node_label=enter_label (label_name,IMPORT_LABEL | EA_LABEL); + node_label=enter_label (label_name, +#if defined (G_A64) && defined (LINUX) + !pic_sl_mod_import ? IMPORT_LABEL | EA_LABEL | USE_GOT_LABEL : IMPORT_LABEL | EA_LABEL); +#else + IMPORT_LABEL | EA_LABEL); +#endif if (ea_label_name[0]=='_' && ea_label_name[1]=='_' && ea_label_name[2]=='\0'){ if (eval_fill_label==NULL) - eval_fill_label=enter_label ("eval_fill",IMPORT_LABEL); + eval_fill_label=enter_label ("eval_fill", +#if defined (G_A64) && defined (LINUX) + rts_got_flag ? (IMPORT_LABEL | USE_GOT_LABEL) : +#endif + IMPORT_LABEL); node_label->label_ea_label=eval_fill_label; } else { ea_label=enter_label (ea_label_name,0); @@ -9409,6 +9723,10 @@ void code_implab_node_entry (char *label_name,char *ea_label_name) void code_implab (char *label_name) { +#if defined (G_A64) && defined (LINUX) + if (!pic_sl_mod_import) + enter_label (label_name,IMPORT_LABEL | USE_GOT_LABEL); +#endif /* enter_label (label_name,IMPORT_LABEL); */ } @@ -10011,6 +10329,7 @@ void initialize_coding (VOID) INT_label=BOOL_label=CHAR_label=REAL_label=FILE_label=_STRING__label=_ARRAY__label=NULL; #if defined (G_A64) && defined (LINUX) + _STRING__0_label=NULL; pic_sl_mod_import=!rts_got_flag; #endif @@ -148,6 +148,7 @@ void code_jmp_eval (VOID); void code_jmp_eval_upd (VOID); void code_jmp_false (char label_name[]); void code_jmp_true (char label_name[]); +void code_jrsr (char label_name[]); void code_jsr (char label_name[]); void code_jsr_ap (int n_args); void code_jsr_eval (int a_offset); @@ -2407,6 +2407,7 @@ static void put_instructions_in_table (void) put_instruction_name ("jmp_false", parse_instruction_a, code_jmp_false ); put_instruction_name ("jmp_not_eqZ", parse_instruction_z_a, code_jmp_not_eqZ ); put_instruction_name ("jmp_true", parse_instruction_a, code_jmp_true ); + put_instruction_name ("jrsr", parse_instruction_a, code_jrsr ); put_instruction_name ("jsr", parse_instruction_a, code_jsr ); put_instruction_name ("jsr_ap", parse_instruction_n, code_jsr_ap ); put_instruction_name ("jsr_eval", parse_instruction_n, code_jsr_eval ); diff --git a/cginstructions.c b/cginstructions.c index aa75489..25ea347 100644 --- a/cginstructions.c +++ b/cginstructions.c @@ -3649,11 +3649,29 @@ static LABEL *enter_c_function_name_label (char *c_function_name) # endif strcpy (&label_name[1],c_function_name); - return enter_label (label_name,0); + return enter_label (label_name, +# if defined (G_A64) && defined (LINUX) + pic_flag ? USE_PLT_LABEL : 0); +# else + 0); +# endif } #else -# define enter_c_function_name_label(c_function_name) enter_label (c_function_name,0) +# if defined (G_A64) && defined (LINUX) +# define enter_c_function_name_label(c_function_name) enter_label (c_function_name, pic_flag ? USE_PLT_LABEL : 0) +# else +# define enter_c_function_name_label(c_function_name) enter_label (c_function_name, 0) +# endif +#endif + +static LABEL *enter_string_to_string_node_label (void) +{ + return enter_label ("string_to_string_node", +#if defined (G_A64) && defined (LINUX) + rts_got_flag ? (USE_GOT_LABEL | IMPORT_LABEL) : #endif + IMPORT_LABEL); +} #if defined (G_POWER) || defined (sparc) static void ccall_load_b_offset (int b_o,int c_parameter_n) @@ -4186,7 +4204,7 @@ void code_ccall (char *c_function_name,char *s,int length) break; case 'S': if (string_to_string_node_label==NULL) - string_to_string_node_label=enter_label ("string_to_string_node",IMPORT_LABEL); + string_to_string_node_label=enter_string_to_string_node_label(); i_move_id_r (0,B_STACK_POINTER,REGISTER_A0); i_jsr_l_id (string_to_string_node_label,0); @@ -4216,7 +4234,7 @@ void code_ccall (char *c_function_name,char *s,int length) break; case 'S': if (string_to_string_node_label==NULL) - string_to_string_node_label=enter_label ("string_to_string_node",IMPORT_LABEL); + string_to_string_node_label=enter_string_to_string_node_label(); i_move_r_r (C_PARAMETER_REGISTER_0,REGISTER_A0); i_sub_i_r (STACK_ELEMENT_SIZE,B_STACK_POINTER); @@ -4520,7 +4538,7 @@ void code_ccall (char *c_function_name,char *s,int length) break; case 'S': if (string_to_string_node_label==NULL) - string_to_string_node_label=enter_label ("string_to_string_node",IMPORT_LABEL); + string_to_string_node_label=enter_string_to_string_node_label(); i_move_pi_r (B_STACK_POINTER,REGISTER_A0); i_jsr_l (string_to_string_node_label,0); i_move_r_id (REGISTER_A0,0,A_STACK_POINTER); @@ -4563,7 +4581,7 @@ void code_ccall (char *c_function_name,char *s,int length) break; case 'S': if (string_to_string_node_label==NULL) - string_to_string_node_label=enter_label ("string_to_string_node",IMPORT_LABEL); + string_to_string_node_label=enter_string_to_string_node_label(); i_move_r_r (REGISTER_D0,REGISTER_A0); i_jsr_l (string_to_string_node_label,0); @@ -5340,7 +5358,7 @@ void code_ccall (char *c_function_name,char *s,int length) switch (s[l]){ case 'S': if (string_to_string_node_label==NULL) - string_to_string_node_label=enter_label ("string_to_string_node",IMPORT_LABEL); + string_to_string_node_label=enter_string_to_string_node_label(); i_move_pi_r (B_STACK_POINTER,REGISTER_A0); i_jsr_l (string_to_string_node_label,0); i_move_r_id (REGISTER_A0,0,A_STACK_POINTER); @@ -5412,7 +5430,7 @@ void code_ccall (char *c_function_name,char *s,int length) break; case 'S': if (string_to_string_node_label==NULL) - string_to_string_node_label=enter_label ("string_to_string_node",IMPORT_LABEL); + string_to_string_node_label=enter_string_to_string_node_label(); i_move_r_r (REGISTER_D0,REGISTER_A0); i_jsr_l (string_to_string_node_label,0); @@ -6105,7 +6123,7 @@ void code_centry (char *c_function_name,char *clean_function_label,char *s,int l offset-=8; else if (c=='S'){ if (string_to_string_node_label==NULL) - string_to_string_node_label=enter_label ("string_to_string_node",IMPORT_LABEL); + string_to_string_node_label=enter_string_to_string_node_label(); offset-=STACK_ELEMENT_SIZE; i_move_id_r (offset,B_STACK_POINTER,REGISTER_A0); i_jsr_l (string_to_string_node_label,0); @@ -6880,6 +6898,11 @@ void code_catS (int source_offset_1,int source_offset_2,int destination_offset) INSTRUCTION_GRAPH graph_1,graph_2,graph_3; if (cat_string_label==NULL) +#if defined (G_A64) && defined (LINUX) + if (rts_got_flag) + cat_string_label=enter_label ("cat_string",IMPORT_LABEL | USE_GOT_LABEL); + else +#endif cat_string_label=enter_label ("cat_string",IMPORT_LABEL); graph_1=s_get_a (source_offset_1); @@ -809,7 +809,7 @@ void i_jsr_id (int offset,int register_1,int n_a_registers) instruction->instruction_parameters[0].parameter_offset=offset; instruction->instruction_parameters[0].parameter_data.reg.r=register_1; - instruction->instruction_parameters[0].parameter_data.reg.u=n_a_registers; + instruction->instruction_parameters[0].parameter_data.reg.u=n_a_registers; /* for parallel code on MC680x0 */ } void i_jsr_l (LABEL *label,int n_a_registers) @@ -821,7 +821,7 @@ void i_jsr_l (LABEL *label,int n_a_registers) instruction->instruction_parameters[0].parameter_type=P_LABEL; instruction->instruction_parameters[0].parameter_data.l=label; - instruction->instruction_parameters[0].parameter_offset=n_a_registers; + instruction->instruction_parameters[0].parameter_offset=n_a_registers; /* for parallel code on MC680x0 */ } #else void i_jsr_id_id (int offset_1,int register_1,int offset_2) @@ -40,6 +40,9 @@ typedef struct label { #ifdef G_POWER struct toc_label * u_toc_labels; /* cgpwas.c */ #endif +#if defined (G_A64) && defined (LINUX) + struct label * u_got_jump_label; /* cgaas.c */ +#endif } label_u2; WORD label_last_lea_arity; } LABEL; @@ -49,6 +52,9 @@ typedef struct label { #ifdef G_POWER # define label_toc_labels label_u2.u_toc_labels #endif +#if defined (G_A64) && defined (LINUX) +# define label_got_jump_label label_u2.u_got_jump_label +#endif #define label_last_lea label_u1.u_last_lea #define label_ea_label label_u1.u_ea_label @@ -68,7 +74,14 @@ typedef struct label { # define DOT_O_BEFORE_LABEL 2048 # define STUB_GENERATED 4096 #endif +#if defined (G_A64) && defined (LINUX) +# define USE_PLT_LABEL 4096 +#endif #define CMP_BRANCH_BLOCK_LABEL 8192 +#if defined (G_A64) && defined (LINUX) +# define USE_GOT_LABEL 16384 +# define HAS_GOT_JUMP_LABEL 32768 +#endif struct label_node { struct label_node * label_node_left; |