From 8afac173dac7b0bbd4e8d441b58b5c2e57658033 Mon Sep 17 00:00:00 2001 From: John van Groningen Date: Thu, 22 Oct 2015 12:54:53 +0000 Subject: add option -pic to generate position independent code on ARM --- cg.c | 8 ++- cg.h | 4 +- cgarmas.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 157 insertions(+), 50 deletions(-) diff --git a/cg.c b/cg.c index 19cc953..7e8f16d 100644 --- a/cg.c +++ b/cg.c @@ -107,8 +107,10 @@ int profile_table_flag; #ifdef G_POWER int fmadd_flag=1; #endif -#if defined (LINUX) && defined (G_AI64) +#if (defined (LINUX) && defined (G_AI64)) || defined (ARM) int pic_flag=0; +#endif +#if defined (LINUX) && defined (G_AI64) int rts_got_flag=0; char **sl_mods; char *no_sl_mods=NULL; @@ -759,6 +761,10 @@ int main (int argc,char **argv) else if (!strcmp (s,"sse64")) sse_128=0; #endif +#ifdef ARM + else if (!strcmp (s,"pic")) + pic_flag=1; +#endif #if defined (LINUX) && defined (G_AI64) else if (!strcmp (s,"pic")){ pic_flag=1; diff --git a/cg.h b/cg.h index 5cdad7f..c7ebd86 100644 --- a/cg.h +++ b/cg.h @@ -34,8 +34,10 @@ extern int profile_table_flag; extern int fmadd_flag; #endif -#if defined (LINUX) && defined (G_AI64) +#if (defined (LINUX) && defined (G_AI64)) || defined (ARM) extern int pic_flag; +#endif +#if defined (LINUX) && defined (G_AI64) extern int rts_got_flag; #endif diff --git a/cgarmas.c b/cgarmas.c index 52680b5..a5f8b9c 100644 --- a/cgarmas.c +++ b/cgarmas.c @@ -179,9 +179,10 @@ static void write_l (int c) #define CALL_RELOCATION 1 #define BRANCH_RELOCATION 2 #define JUMP_RELOCATION 3 -#define DUMMY_BRANCH_RELOCATION 5 -#define LDR_OFFSET_RELOCATION 6 /* R_ARM_LDR_PC_G0 */ -#define VLDR_OFFSET_RELOCATION 7 /* R_ARM_LDC_PC_G0 */ +#define DUMMY_BRANCH_RELOCATION 4 +#define LDR_OFFSET_RELOCATION 5 /* R_ARM_LDR_PC_G0 */ +#define VLDR_OFFSET_RELOCATION 6 /* R_ARM_LDC_PC_G0 */ +#define RELATIVE_LONG_WORD_RELOCATION 7 struct relocation { struct relocation * next; @@ -347,7 +348,7 @@ static void store_c (int c) } } -static void store_l (register ULONG i) +static void store_l (ULONG i) { if (code_buffer_p>=literal_table_at_buffer_p) write_branch_and_literals(); @@ -358,6 +359,14 @@ static void store_l (register ULONG i) store_c (i>>24); } +static void store_l_no_literal_table (ULONG i) +{ + store_c (i); + store_c (i>>8); + store_c (i>>16); + store_c (i>>24); +} + void store_long_word_in_data_section (ULONG c) { if (data_buffer_free>=4){ @@ -476,6 +485,22 @@ static void store_label_in_code_section (struct label *label) new_relocation->relocation_kind=LONG_WORD_RELOCATION; } +static void store_relative_label_in_code_section (struct label *label) +{ + struct relocation *new_relocation; + + new_relocation=fast_memory_allocate_type (struct relocation); + ++n_code_relocations; + + *last_code_relocation_l=new_relocation; + last_code_relocation_l=&new_relocation->next; + new_relocation->next=NULL; + + new_relocation->relocation_label=label; + new_relocation->relocation_offset=CURRENT_CODE_OFFSET-4; + new_relocation->relocation_kind=RELATIVE_LONG_WORD_RELOCATION; +} + struct literal_entry { LABEL * le_label; int le_offset; @@ -494,24 +519,34 @@ static void write_literals (void) if (literal_entry!=NULL){ for (; literal_entry!=NULL; literal_entry=literal_entry->le_next){ + int load_data_offset,current_code_offset; + + load_data_offset = literal_entry->le_load_instruction_label.label_offset; + current_code_offset = CURRENT_CODE_OFFSET; + literal_entry->le_load_instruction_label.label_flags=0; literal_entry->le_load_instruction_label.label_id=TEXT_LABEL_ID; #ifdef FUNCTION_LEVEL_LINKING literal_entry->le_load_instruction_label.label_object_label=code_object_label; #endif - literal_entry->le_load_instruction_label.label_offset=CURRENT_CODE_OFFSET; + literal_entry->le_load_instruction_label.label_offset=current_code_offset; if (literal_entry->le_label){ literal_entry->le_label->label_flags &= ~HAS_LITERAL_ENTRY; - store_l (literal_entry->le_offset); - store_label_in_code_section (literal_entry->le_label); + if (!pic_flag){ + store_l_no_literal_table (literal_entry->le_offset); + store_label_in_code_section (literal_entry->le_label); + } else { + store_l_no_literal_table (current_code_offset - load_data_offset -12 + literal_entry->le_offset); + store_relative_label_in_code_section (literal_entry->le_label); + } } else { if (literal_entry->le_r_p==NULL){ - store_l (literal_entry->le_offset); + store_l_no_literal_table (literal_entry->le_offset); } else { // to do: align 8 - store_l (((LONG*)(literal_entry->le_r_p))[0]); - store_l (((LONG*)(literal_entry->le_r_p))[1]); + store_l_no_literal_table (((LONG*)(literal_entry->le_r_p))[0]); + store_l_no_literal_table (((LONG*)(literal_entry->le_r_p))[1]); } } } @@ -586,17 +621,36 @@ static void as_literal_label (struct label *label,int relocation_kind) new_relocation->relocation_label=label; new_relocation->relocation_offset=current_code_offset; + label->label_offset=current_code_offset; /* for pic store offset of load instead, label offset stored by write_literals */ #ifdef FUNCTION_LEVEL_LINKING new_relocation->relocation_object_label=code_object_label; #endif new_relocation->relocation_kind=relocation_kind; } -static void as_literal_entry (LABEL *label,int offset) +static void as_literal_constant_entry (int offset) +{ + struct literal_entry *new_literal_entry; + + new_literal_entry=allocate_memory_from_heap (sizeof (struct literal_entry)); + + new_literal_entry->le_label=NULL; + new_literal_entry->le_offset=offset; + new_literal_entry->le_r_p=NULL; + + *literal_entry_l=new_literal_entry; + literal_entry_l=&new_literal_entry->le_next; + + new_literal_entry->le_next=NULL; + + as_literal_label (&new_literal_entry->le_load_instruction_label,LDR_OFFSET_RELOCATION); +} + +static void as_literal_label_entry (LABEL *label,int offset) { struct literal_entry *new_literal_entry; - if (label!=NULL && label->label_flags & HAS_LITERAL_ENTRY && label->label_literal_entry->le_offset==offset) + if (label->label_flags & HAS_LITERAL_ENTRY && label->label_literal_entry->le_offset==offset) new_literal_entry=label->label_literal_entry; else { new_literal_entry=allocate_memory_from_heap (sizeof (struct literal_entry)); @@ -610,7 +664,7 @@ static void as_literal_entry (LABEL *label,int offset) new_literal_entry->le_next=NULL; - if (label!=NULL){ + if (!pic_flag){ label->label_flags |= HAS_LITERAL_ENTRY; label->label_literal_entry=new_literal_entry; } @@ -795,23 +849,11 @@ static void as_move_i_r (int i,int reg1) store_l_is (0xe3e00000 | (reg_num (reg1)<<12),~i,shift); /* mvn rd,#i<instruction_parameters[1].parameter_data.reg.r, instruction->instruction_parameters[1].parameter_data.reg.r); @@ -3139,7 +3202,7 @@ static void as_garbage_collect_test (struct basic_block *block) as_subs_is_r_r (n_cells,shift,REGISTER_R5,REGISTER_R5); } else { store_l (0xe59f0000 | (reg_num (REGISTER_S0)<<12)); /* ldr rt,[pc+imm] */ - as_literal_entry (NULL,n_cells); + as_literal_constant_entry (n_cells); as_x_op_r_r_r ((ARM_OP_SUB<<1) | 1,REGISTER_S0,REGISTER_R5,REGISTER_R5); /* subs */ } @@ -3260,14 +3323,14 @@ static void as_node_entry_info (struct basic_block *block) n_node_arguments=1; if (n_node_arguments>=0 && block->block_ea_label!=eval_fill_label){ -#if 1 if (!block->block_profile){ as_move_l_r (block->block_ea_label,REGISTER_A3); store_l (0xea000000); /* b */ as_branch_label (eval_upd_labels[n_node_arguments],JUMP_RELOCATION); - as_nop(); + if (!pic_flag) + as_nop(); } else { as_move_l_r (block->block_ea_label,REGISTER_D0); as_move_l_r (block->block_profile_function_label,REGISTER_A3); @@ -3275,13 +3338,6 @@ static void as_node_entry_info (struct basic_block *block) store_l (0xea000000); /* b */ as_branch_label (eval_upd_labels[n_node_arguments],JUMP_RELOCATION); } -#else - as_move_l_r (eval_upd_labels[n_node_arguments],REGISTER_D0); - as_move_l_r (block->block_ea_label,REGISTER_A3); - - store_c (0377); - store_c (0340 | reg_num (REGISTER_D0)); /* jmp d0 */ -#endif } else { store_l (0xea000000); /* b */ as_branch_label (block->block_ea_label,JUMP_RELOCATION); @@ -3292,13 +3348,19 @@ static void as_node_entry_info (struct basic_block *block) if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag)){ store_l (0); - store_label_in_code_section (block->block_descriptor); + if (!pic_flag) + store_label_in_code_section (block->block_descriptor); + else + store_relative_label_in_code_section (block->block_descriptor); } else store_l (0); } else if (block->block_descriptor!=NULL && (block->block_n_node_arguments<0 || parallel_flag || module_info_flag)){ store_l (0); - store_label_in_code_section (block->block_descriptor); + if (!pic_flag) + store_label_in_code_section (block->block_descriptor); + else + store_relative_label_in_code_section (block->block_descriptor); } /* else store_l (0); @@ -4109,6 +4171,23 @@ static void relocate_code (void) case LONG_WORD_RELOCATION: relocation_p=&relocation->next; + if (label->label_id==TEXT_LABEL_ID || (label->label_id==DATA_LABEL_ID +#if defined (RELOCATIONS_RELATIVE_TO_EXPORTED_DATA_LABEL) && defined (FUNCTION_LEVEL_LINKING) + && !((label->label_flags & EXPORT_LABEL) && label->label_object_label->object_label_kind==EXPORTED_DATA_LABEL) +#endif + )) + { + instruction_offset=relocation->relocation_offset; + v=label->label_offset; +#ifdef FUNCTION_LEVEL_LINKING + v -= label->label_object_label->object_label_offset; +#endif + break; + } else + continue; + case RELATIVE_LONG_WORD_RELOCATION: + relocation_p=&relocation->next; + if (label->label_id==TEXT_LABEL_ID || (label->label_id==DATA_LABEL_ID #if defined (RELOCATIONS_RELATIVE_TO_EXPORTED_DATA_LABEL) && defined (FUNCTION_LEVEL_LINKING) && !((label->label_flags & EXPORT_LABEL) && label->label_object_label->object_label_kind==EXPORTED_DATA_LABEL) @@ -4691,6 +4770,26 @@ static void write_code_relocations (void) write_l (ELF32_R_INFO (elf_label_number (label),R_ARM_ABS32)); #else write_l (ELF32_R_INFO (label->label_id,R_ARM_ABS32)); +#endif + break; + } + case RELATIVE_LONG_WORD_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_l (relocation->relocation_offset); +#ifdef FUNCTION_LEVEL_LINKING + write_l (ELF32_R_INFO (elf_label_number (label),R_ARM_REL32)); +#else + write_l (ELF32_R_INFO (label->label_id,R_ARM_REL32)); #endif break; } -- cgit v1.2.3