Verified Commit 6c20f7be authored by Camil Staps's avatar Camil Staps 🚀

Optimize linker (2x; assume symbols in source files are sorted)

parent d749afd5
......@@ -16,12 +16,6 @@
struct program pgrm;
uint32_t last_d, last_jsr_with_d;
struct label_node {
struct label_node *label_node_left;
struct label_node *label_node_right;
struct label *label_node_label_p;
};
struct label_node *labels;
uint32_t label_id;
uint32_t global_label_count;
......@@ -176,6 +170,89 @@ struct label *enter_label(char *label_name) {
return new_label_p;
}
#ifdef LINKER
struct label *find_label(char *label_name) {
struct label_node *label_node_p=labels;
while (label_node_p!=NULL) {
int r=strcmp(label_name,label_node_p->label_node_label_p->label_name);
if (r==0)
return label_node_p->label_node_label_p;
else if (r<0)
label_node_p=label_node_p->label_node_left;
else
label_node_p=label_node_p->label_node_right;
}
return NULL;
}
static struct label_node **merge_label_tree_with_list(struct label_node **dest,
struct label_node *tree,
struct label_node **list,unsigned int *list_i,unsigned int list_size) {
if (tree->label_node_left!=NULL)
dest=merge_label_tree_with_list(dest,tree->label_node_left,list,list_i,list_size);
unsigned int i=*list_i;
int r=-1;
while (i<list_size &&
(r=strcmp(list[i]->label_node_label_p->label_name,tree->label_node_label_p->label_name))<0)
*dest++=list[i++];
*list_i=i;
if (r==0) {
EPRINTF("internal error: %s redefined\n",tree->label_node_label_p->label_name);
exit(-1);
}
*dest++=tree;
if (tree->label_node_right!=NULL)
dest=merge_label_tree_with_list(dest,tree->label_node_right,list,list_i,list_size);
return dest;
}
static struct label_node *update_label_node_pointers(
struct label_node **sorted_list,int lft,int rgt) {
if (rgt<lft)
return NULL;
if (rgt==lft) {
sorted_list[lft]->label_node_left=NULL;
sorted_list[lft]->label_node_right=NULL;
return sorted_list[lft];
}
int middle=lft+(rgt-lft)/2;
sorted_list[middle]->label_node_left =update_label_node_pointers(sorted_list,lft,middle-1);
sorted_list[middle]->label_node_right=update_label_node_pointers(sorted_list,middle+1,rgt);
return sorted_list[middle];
}
void merge_new_labels_and_rebalance(struct label_node **new_labels,unsigned int n_new_labels) {
for (int i=0; i<n_new_labels; i++) {
struct label *label=new_labels[i]->label_node_label_p;
label->label_id=label_id++;
make_label_global(label);
}
if (labels==NULL) {
labels=update_label_node_pointers(new_labels,0,label_id-1);
return;
}
struct label_node **temp_list=safe_malloc(label_id*sizeof(struct label_node*));
unsigned int list_i=0;
struct label_node **temp_list_end=merge_label_tree_with_list(temp_list,labels,new_labels,&list_i,n_new_labels);
while (list_i<n_new_labels)
*temp_list_end++=new_labels[list_i++];
labels=update_label_node_pointers(temp_list,0,label_id-1);
free(temp_list);
}
#endif
struct label *new_label_at_offset(uint32_t offset) {
char name[16];
snprintf(name, 16, "i%x", offset);
......
......@@ -12,6 +12,12 @@ struct label {
int32_t label_module_n;
};
struct label_node {
struct label_node *label_node_left;
struct label_node *label_node_right;
struct label *label_node_label_p;
};
typedef struct relocation {
uint32_t relocation_offset;
struct label *relocation_label;
......@@ -31,8 +37,15 @@ struct label *enter_label(char *label_name);
struct label *new_internal_label(void);
struct label *new_label_at_offset(uint32_t offset);
void make_label_global(struct label *label);
#ifdef LINKER
void merge_new_labels_and_rebalance(struct label_node **new_labels,unsigned int n_new_labels);
struct label *find_label(char *label_name);
#endif
struct relocation *add_code_relocation(struct label *label, uint32_t offset);
struct relocation *add_data_relocation(struct label *label, uint32_t offset);
void add_words_in_strings(uint32_t val);
void add_string_information(uint32_t data_offset);
void store_string(char *string,int string_length,int include_terminator);
......
......@@ -144,9 +144,20 @@ void next_state(struct parser *state) {
return;
case PS_data:
state->state = PS_symbol_table;
#ifdef LINKER
state->new_label_nodes=safe_malloc(state->program->symbol_table_size*sizeof(struct label_node*));
state->n_labels=0;
#endif
if (state->program->symbol_table_size > 0)
return;
case PS_symbol_table:
#ifdef LINKER
merge_new_labels_and_rebalance(state->new_label_nodes,state->n_labels);
free(state->new_label_nodes);
if (state->is_main_module && state->program->start_symbol_id<state->program->symbol_table_size)
code_start(state->program->symbol_table[state->program->start_symbol_id].name);
#endif
state->state = PS_code_reloc;
if (state->code_reloc_size > 0)
return;
......@@ -609,14 +620,28 @@ int parse_program(struct parser *state, struct char_provider *cp) {
}
#elif defined(LINKER)
if (state->program->symbol_table[state->ptr].name[0] != '\0') {
struct label *label = enter_label(state->program->symbol_table[state->ptr].name);
if (state->program->symbol_table[state->ptr].offset != -1)
label->label_offset = state->program->symbol_table[state->ptr].offset;
make_label_global(label);
struct label *label=find_label(state->program->symbol_table[state->ptr].name);
if (label==NULL) {
label=safe_malloc(sizeof(struct label));
label->label_name=safe_malloc(strlen(state->program->symbol_table[state->ptr].name)+1);
strcpy(label->label_name,state->program->symbol_table[state->ptr].name);
label->label_id=-1;
label->label_offset=state->program->symbol_table[state->ptr].offset;
label->label_module_n=-2;
struct label_node *node=safe_malloc(sizeof(struct label_node));
node->label_node_left=NULL;
node->label_node_right=NULL;
node->label_node_label_p=label;
state->new_label_nodes[state->n_labels++]=node;
} else {
if (state->program->symbol_table[state->ptr].offset!=-1)
label->label_offset=state->program->symbol_table[state->ptr].offset;
make_label_global(label);
}
}
if (state->is_main_module && state->program->start_symbol_id==state->ptr)
code_start(state->program->symbol_table[state->ptr].name);
#endif
if (++state->ptr >= state->program->symbol_table_size)
next_state(state);
......
......@@ -4,6 +4,10 @@
#include "settings.h"
#include "util.h"
#ifdef LINKER
# include "bcgen_instructions.h"
#endif
enum parse_state {
PS_init,
PS_code,
......@@ -53,6 +57,9 @@ struct parser {
uint32_t code_offset;
uint32_t data_offset;
int is_main_module:1;
struct label_node **new_label_nodes;
unsigned int n_labels;
#endif
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment