summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgaas.c309
-rw-r--r--cgaas.h3
-rw-r--r--cgcode.c595
-rw-r--r--cgcodep.h1
-rw-r--r--cginput.c1
-rw-r--r--cginstructions.c41
-rw-r--r--cglin.c4
-rw-r--r--cgtypes.h13
8 files changed, 779 insertions, 188 deletions
diff --git a/cgaas.c b/cgaas.c
index f1ef694..707082a 100644
--- a/cgaas.c
+++ b/cgaas.c
@@ -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");
diff --git a/cgaas.h b/cgaas.h
index b92df25..0199130 100644
--- a/cgaas.h
+++ b/cgaas.h
@@ -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);
diff --git a/cgcode.c b/cgcode.c
index 6512c83..36bea5f 100644
--- a/cgcode.c
+++ b/cgcode.c
@@ -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
diff --git a/cgcodep.h b/cgcodep.h
index b5ee038..41cd9fb 100644
--- a/cgcodep.h
+++ b/cgcodep.h
@@ -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);
diff --git a/cginput.c b/cginput.c
index bc62e50..9220932 100644
--- a/cginput.c
+++ b/cginput.c
@@ -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);
diff --git a/cglin.c b/cglin.c
index bcfeca8..36d766f 100644
--- a/cglin.c
+++ b/cglin.c
@@ -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)
diff --git a/cgtypes.h b/cgtypes.h
index d299076..07b44bf 100644
--- a/cgtypes.h
+++ b/cgtypes.h
@@ -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;