summaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2017-11-10 14:27:42 -0800
committerMax Filippov <jcmvbkbc@gmail.com>2017-11-27 15:13:00 -0800
commit46888d710015aa8d4bb3c2dac7aa6505d6ac8227 (patch)
tree017a7b95e02d879c357234f1a0422b5068cd0a1c /gas
parent1c2649f50f4e40c07840f45c4d237efcdd02e8e2 (diff)
gas: xtensa: merge trampoline_frag into xtensa_frag_type
The split between fragS and trampoline_frag doesn't save much space, but makes trampolines management much more awkward. Merge trampoline_frag data into the xtensa_frag_type, which is a part of fragS. No functional changes. gas/ 2017-11-27 Max Filippov <jcmvbkbc@gmail.com> * config/tc-xtensa.c (init_trampoline_frag): Replace pointer to struct trampoline_frag parameter with pointer to fragS. (xg_append_jump): Remove jump_around parameter. (struct trampoline_frag): Remove. (struct trampoline_seg): Change type of trampoline_list from struct trampoline_frag to fragS. (xtensa_create_trampoline_frag): Don't allocate struct trampoline_frag. Initialize new fragS::tc_frag_data fields. (dump_trampolines, xg_relax_trampoline, search_trampolines) (get_best_trampoline, init_trampoline_frag) (add_jump_to_trampoline, relax_frag_immed): Replace pointer to struct trampoline_frag with a pointer to fragS. (xg_append_jump): Remove jump_around parameter, use fragS::tc_frag_data.jump_around_fix instead. (xg_relax_trampoline, init_trampoline_frag) (add_jump_to_trampoline): Don't pass jump_around parameter to xg_append_jump. * config/tc-xtensa.h (struct xtensa_frag_type): Add new fields: needs_jump_around, next_trampoline and jump_around_fix.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog22
-rw-r--r--gas/config/tc-xtensa.c120
-rw-r--r--gas/config/tc-xtensa.h8
3 files changed, 83 insertions, 67 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 82c4f6b7bf..fff3dedc28 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,5 +1,27 @@
2017-11-27 Max Filippov <jcmvbkbc@gmail.com>
+ * config/tc-xtensa.c (init_trampoline_frag): Replace pointer to
+ struct trampoline_frag parameter with pointer to fragS.
+ (xg_append_jump): Remove jump_around parameter.
+ (struct trampoline_frag): Remove.
+ (struct trampoline_seg): Change type of trampoline_list from
+ struct trampoline_frag to fragS.
+ (xtensa_create_trampoline_frag): Don't allocate struct
+ trampoline_frag. Initialize new fragS::tc_frag_data fields.
+ (dump_trampolines, xg_relax_trampoline, search_trampolines)
+ (get_best_trampoline, init_trampoline_frag)
+ (add_jump_to_trampoline, relax_frag_immed): Replace pointer to
+ struct trampoline_frag with a pointer to fragS.
+ (xg_append_jump): Remove jump_around parameter, use
+ fragS::tc_frag_data.jump_around_fix instead.
+ (xg_relax_trampoline, init_trampoline_frag)
+ (add_jump_to_trampoline): Don't pass jump_around parameter to
+ xg_append_jump.
+ * config/tc-xtensa.h (struct xtensa_frag_type): Add new fields:
+ needs_jump_around, next_trampoline and jump_around_fix.
+
+2017-11-27 Max Filippov <jcmvbkbc@gmail.com>
+
* config/tc-xtensa.c (find_trampoline_seg): Move above the first
use.
(xtensa_create_trampoline_frag): Replace trampoline seg search
diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c
index a8ed49b56d..378537c9fb 100644
--- a/gas/config/tc-xtensa.c
+++ b/gas/config/tc-xtensa.c
@@ -484,9 +484,8 @@ static void xtensa_check_frag_count (void);
static void xtensa_create_trampoline_frag (bfd_boolean);
static void xtensa_maybe_create_trampoline_frag (void);
struct trampoline_frag;
-static int init_trampoline_frag (struct trampoline_frag *);
-static fixS *xg_append_jump (fragS *fragP, fixS *jump_around,
- symbolS *sym, offsetT offset);
+static int init_trampoline_frag (fragS *);
+static fixS *xg_append_jump (fragS *fragP, symbolS *sym, offsetT offset);
static void xtensa_maybe_create_literal_pool_frag (bfd_boolean, bfd_boolean);
static bfd_boolean auto_litpools = FALSE;
static int auto_litpool_limit = 10000;
@@ -7350,19 +7349,11 @@ xtensa_end (void)
}
-struct trampoline_frag
-{
- struct trampoline_frag *next;
- bfd_boolean needs_jump_around;
- fragS *fragP;
- fixS *fixP;
-};
-
struct trampoline_seg
{
struct trampoline_seg *next;
asection *seg;
- struct trampoline_frag trampoline_list;
+ fragS trampoline_list;
};
static struct trampoline_seg trampoline_seg_list;
@@ -7446,7 +7437,6 @@ xtensa_create_trampoline_frag (bfd_boolean needs_jump_around)
If that's not enough, oh well. */
struct trampoline_seg *ts = find_trampoline_seg (now_seg);
- struct trampoline_frag *tf;
char *varP;
fragS *fragP;
int size = TRAMPOLINE_FRAG_SIZE;
@@ -7469,12 +7459,10 @@ xtensa_create_trampoline_frag (bfd_boolean needs_jump_around)
trampoline_buf = xtensa_insnbuf_alloc (xtensa_default_isa);
trampoline_slotbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
}
- tf = XNEW (struct trampoline_frag);
- tf->next = ts->trampoline_list.next;
- ts->trampoline_list.next = tf;
- tf->needs_jump_around = needs_jump_around;
- tf->fragP = fragP;
- tf->fixP = NULL;
+ fragP->tc_frag_data.next_trampoline =
+ ts->trampoline_list.tc_frag_data.next_trampoline;
+ ts->trampoline_list.tc_frag_data.next_trampoline = fragP;
+ fragP->tc_frag_data.needs_jump_around = needs_jump_around;
}
@@ -7492,14 +7480,12 @@ dump_trampolines (void)
if (seg == NULL)
continue;
fprintf(stderr, "SECTION %s\n", seg->name);
- struct trampoline_frag *tf = ts->trampoline_list.next;
- for ( ; tf; tf = tf->next)
+ fragS *tf = ts->trampoline_list.tc_frag_data.next_trampoline;
+ for ( ; tf; tf = tf->tc_frag_data.next_trampoline)
{
- if (tf->fragP == NULL)
- continue;
fprintf(stderr, " 0x%08x: fix=%d, jump_around=%s\n",
- (int)tf->fragP->fr_address, (int)tf->fragP->fr_fix,
- tf->needs_jump_around ? "T" : "F");
+ (int)tf->fr_address, (int)tf->fr_fix,
+ tf->tc_frag_data.needs_jump_around ? "T" : "F");
}
}
}
@@ -9199,8 +9185,8 @@ static void xg_relax_trampoline (fragS *fragP, long stretch, long *new_stretch)
if (delta > J_RANGE || delta < -1 * J_RANGE)
{ /* Found an out-of-range jump; scan the list of trampolines for the best match. */
struct trampoline_seg *ts = find_trampoline_seg (now_seg);
- struct trampoline_frag *tf = ts->trampoline_list.next;
- struct trampoline_frag *prev = &ts->trampoline_list;
+ fragS *tf = ts->trampoline_list.tc_frag_data.next_trampoline;
+ fragS *prev = &ts->trampoline_list;
int lower = (target < addr) ? target : addr;
int upper = (target > addr) ? target : addr;
int midpoint = lower + (upper - lower) / 2;
@@ -9210,10 +9196,11 @@ static void xg_relax_trampoline (fragS *fragP, long stretch, long *new_stretch)
/* One trampoline won't suffice; we need multiple jumps.
Jump to the trampoline that's farthest, but still in
range relative to the original "j" instruction. */
- for ( ; tf; prev = tf, tf = tf->next )
+ for ( ; tf; prev = tf, tf = tf->tc_frag_data.next_trampoline)
{
- int this_addr = tf->fragP->fr_address + tf->fragP->fr_fix;
- int next_addr = (tf->next) ? tf->next->fragP->fr_address + tf->next->fragP->fr_fix : 0 ;
+ fragS *next = tf->tc_frag_data.next_trampoline;
+ int this_addr = tf->fr_address + tf->fr_fix;
+ int next_addr = next ? next->fr_address + next->fr_fix : 0 ;
if (addr == lower)
{
@@ -9231,13 +9218,13 @@ static void xg_relax_trampoline (fragS *fragP, long stretch, long *new_stretch)
}
else
{
- struct trampoline_frag *best_tf = NULL;
- struct trampoline_frag *best_tf_prev = NULL;
+ fragS *best_tf = NULL;
+ fragS *best_tf_prev = NULL;
int best_delta = 0;
- for ( ; tf; prev = tf, tf = tf->next )
+ for ( ; tf; prev = tf, tf = tf->tc_frag_data.next_trampoline)
{
- int this_addr = tf->fragP->fr_address + tf->fragP->fr_fix;
+ int this_addr = tf->fr_address + tf->fr_fix;
int this_delta = abs (this_addr - midpoint);
if (!best_tf || this_delta < best_delta)
@@ -9250,7 +9237,7 @@ static void xg_relax_trampoline (fragS *fragP, long stretch, long *new_stretch)
tf = best_tf;
prev = best_tf_prev;
}
- if (tf->fragP == fragP)
+ if (tf == fragP)
{
if (abs (addr - trampaddr) < J_RANGE)
{ /* The trampoline is in range of original; fix it! */
@@ -9258,7 +9245,7 @@ static void xg_relax_trampoline (fragS *fragP, long stretch, long *new_stretch)
new_stretch += init_trampoline_frag (tf) + 3;
/* Assemble a jump to the target label in the trampoline frag. */
- newfixP = xg_append_jump (fragP, tf->fixP,
+ newfixP = xg_append_jump (fragP,
fixP->fx_addsy, fixP->fx_offset);
/* Adjust the fixup for the original "j" instruction to
@@ -9282,7 +9269,8 @@ static void xg_relax_trampoline (fragS *fragP, long stretch, long *new_stretch)
frag_wane (fragP);
fragP->fr_subtype = 0;
/* Remove from the trampoline_list. */
- prev->next = tf->next;
+ prev->tc_frag_data.next_trampoline =
+ tf->tc_frag_data.next_trampoline;
if (fragP == fixup_cache.first_frag)
fixup_cache.first_frag = NULL;
break;
@@ -9877,12 +9865,12 @@ bytes_to_stretch (fragS *this_frag,
}
-static struct trampoline_frag *
+static fragS *
search_trampolines (TInsn *tinsn, fragS *fragP, bfd_boolean unreachable_only)
{
struct trampoline_seg *ts = find_trampoline_seg (now_seg);
- struct trampoline_frag *tf = (ts) ? ts->trampoline_list.next : NULL;
- struct trampoline_frag *best_tf = NULL;
+ fragS *tf = ts ? ts->trampoline_list.tc_frag_data.next_trampoline : NULL;
+ fragS *best_tf = NULL;
int best_delta = 0;
int best_addr = 0;
symbolS *sym = tinsn->tok[0].X_add_symbol;
@@ -9900,11 +9888,12 @@ search_trampolines (TInsn *tinsn, fragS *fragP, bfd_boolean unreachable_only)
/* One trampoline won't do; we need multiple.
Choose the farthest trampoline that's still in range of the original
and let a later pass finish the job. */
- for ( ; tf; tf = tf->next)
+ for ( ; tf; tf = tf->tc_frag_data.next_trampoline)
{
- int next_addr = (tf->next) ? tf->next->fragP->fr_address + tf->next->fragP->fr_fix : 0;
+ fragS *next = tf->tc_frag_data.next_trampoline;
+ int next_addr = next ? next->fr_address + next->fr_fix : 0;
- this_addr = tf->fragP->fr_address + tf->fragP->fr_fix;
+ this_addr = tf->fr_address + tf->fr_fix;
if (lower == addr)
{
/* Forward jump. */
@@ -9923,11 +9912,11 @@ search_trampolines (TInsn *tinsn, fragS *fragP, bfd_boolean unreachable_only)
return NULL;
}
- for ( ; tf; tf = tf->next)
+ for ( ; tf; tf = tf->tc_frag_data.next_trampoline)
{
- this_addr = tf->fragP->fr_address + tf->fragP->fr_fix;
+ this_addr = tf->fr_address + tf->fr_fix;
this_delta = abs (this_addr - midpoint);
- if (unreachable_only && tf->needs_jump_around)
+ if (unreachable_only && tf->tc_frag_data.needs_jump_around)
continue;
if (!best_tf || this_delta < best_delta)
{
@@ -9947,10 +9936,10 @@ search_trampolines (TInsn *tinsn, fragS *fragP, bfd_boolean unreachable_only)
}
-static struct trampoline_frag *
+static fragS *
get_best_trampoline (TInsn *tinsn, fragS *fragP)
{
- struct trampoline_frag *tf = NULL;
+ fragS *tf = NULL;
tf = search_trampolines (tinsn, fragP, TRUE); /* Try unreachable first. */
@@ -9965,22 +9954,21 @@ static void
check_and_update_trampolines (void)
{
struct trampoline_seg *ts = find_trampoline_seg (now_seg);
- struct trampoline_frag *tf = ts->trampoline_list.next;
- struct trampoline_frag *prev = &ts->trampoline_list;
+ fragS *tf = ts->trampoline_list.tc_frag_data.next_trampoline;
+ fragS *prev = &ts->trampoline_list;
- for ( ; tf; prev = tf, tf = tf->next)
+ for ( ; tf; prev = tf, tf = tf->tc_frag_data.next_trampoline)
{
- if (tf->fragP->fr_var < 3)
+ if (tf->fr_var < 3)
{
- frag_wane (tf->fragP);
- prev->next = tf->next;
- tf->fragP = NULL;
+ frag_wane (tf);
+ prev->tc_frag_data.next_trampoline =
+ tf->tc_frag_data.next_trampoline;
}
}
}
-static fixS *xg_append_jump (fragS *fragP, fixS *jump_around,
- symbolS *sym, offsetT offset)
+static fixS *xg_append_jump (fragS *fragP, symbolS *sym, offsetT offset)
{
fixS *fixP;
TInsn insn;
@@ -10006,17 +9994,16 @@ static fixS *xg_append_jump (fragS *fragP, fixS *jump_around,
fragP->fr_var -= 3;
/* Adjust the jump around this trampoline (if present). */
- if (jump_around)
- jump_around->fx_offset += 3;
+ if (fragP->tc_frag_data.jump_around_fix)
+ fragP->tc_frag_data.jump_around_fix->fx_offset += 3;
return fixP;
}
static int
-init_trampoline_frag (struct trampoline_frag *trampP)
+init_trampoline_frag (fragS *fp)
{
- fragS *fp = trampP->fragP;
int growth = 0;
if (fp->fr_fix == 0)
@@ -10027,9 +10014,9 @@ init_trampoline_frag (struct trampoline_frag *trampP)
sprintf (label, ".L0_TR_%p", fp);
lsym = (symbolS *)local_symbol_make (label, now_seg, 0, fp);
fp->fr_symbol = lsym;
- if (trampP->needs_jump_around)
+ if (fp->tc_frag_data.needs_jump_around)
{
- trampP->fixP = xg_append_jump (fp, NULL, lsym, 3);
+ fp->tc_frag_data.jump_around_fix = xg_append_jump (fp, lsym, 3);
growth = 3;
}
}
@@ -10038,9 +10025,8 @@ init_trampoline_frag (struct trampoline_frag *trampP)
static int
-add_jump_to_trampoline (struct trampoline_frag *trampP, fragS *origfrag)
+add_jump_to_trampoline (fragS *tramp, fragS *origfrag)
{
- fragS *tramp = trampP->fragP;
int i, slot = -1;
for (i = 0; i < MAX_SLOTS; ++i)
@@ -10053,7 +10039,7 @@ add_jump_to_trampoline (struct trampoline_frag *trampP, fragS *origfrag)
gas_assert (slot >= 0 && slot < MAX_SLOTS);
/* Assemble a jump to the target label in the trampoline frag. */
- xg_append_jump (tramp, trampP->fixP,
+ xg_append_jump (tramp,
origfrag->tc_frag_data.slot_symbols[slot],
origfrag->tc_frag_data.slot_offsets[slot]);
@@ -10216,7 +10202,7 @@ relax_frag_immed (segT segP,
if (!xg_symbolic_immeds_fit (jinsn, segP, fragP, fragP->fr_offset, total_text_diff))
{
- struct trampoline_frag *tf = get_best_trampoline (jinsn, fragP);
+ fragS *tf = get_best_trampoline (jinsn, fragP);
if (tf)
{
diff --git a/gas/config/tc-xtensa.h b/gas/config/tc-xtensa.h
index 912c890eed..59907a59d3 100644
--- a/gas/config/tc-xtensa.h
+++ b/gas/config/tc-xtensa.h
@@ -236,6 +236,10 @@ struct xtensa_frag_type
align branch targets as if it were a normal narrow instruction. */
unsigned int is_aligning_branch : 1;
+ /* A trampoline frag that is located in the middle of code and thus
+ needs a jump around. */
+ unsigned int needs_jump_around : 1;
+
/* For text fragments that can generate literals at relax time, this
variable points to the frag where the literal will be stored. For
literal frags, this variable points to the nearest literal pool
@@ -269,6 +273,10 @@ struct xtensa_frag_type
symbolS *slot_symbols[MAX_SLOTS];
offsetT slot_offsets[MAX_SLOTS];
+ /* For trampoline fragments. */
+ fragS *next_trampoline;
+ struct fix *jump_around_fix;
+
/* When marking frags after this one in the chain as no transform,
cache the last one in the chain, so that we can skip to the
end of the chain. */