+/* Various frobbings of labels and their addresses. */
+
+/* Symbols labelling the current insn. */
+struct insn_label_list
+{
+ struct insn_label_list *next;
+ symbolS *label;
+};
+
+static struct insn_label_list *insn_labels;
+static struct insn_label_list *free_insn_labels;
+
+static void
+ppc_record_label (symbolS *sym)
+{
+ struct insn_label_list *l;
+
+ if (free_insn_labels == NULL)
+ l = XNEW (struct insn_label_list);
+ else
+ {
+ l = free_insn_labels;
+ free_insn_labels = l->next;
+ }
+
+ l->label = sym;
+ l->next = insn_labels;
+ insn_labels = l;
+}
+
+static void
+ppc_clear_labels (void)
+{
+ while (insn_labels != NULL)
+ {
+ struct insn_label_list *l = insn_labels;
+ insn_labels = l->next;
+ l->next = free_insn_labels;
+ free_insn_labels = l;
+ }
+}
+
+void
+ppc_start_line_hook (void)
+{
+ ppc_clear_labels ();
+}
+
+void
+ppc_new_dot_label (symbolS *sym)
+{
+ ppc_record_label (sym);
+#ifdef OBJ_XCOFF
+ /* Anchor this label to the current csect for relocations. */
+ symbol_get_tc (sym)->within = ppc_current_csect;
+#endif
+}
+
+void
+ppc_frob_label (symbolS *sym)
+{
+ ppc_record_label (sym);
+
+#ifdef OBJ_XCOFF
+ /* Set the class of a label based on where it is defined. This handles
+ symbols without suffixes. Also, move the symbol so that it follows
+ the csect symbol. */
+ if (ppc_current_csect != (symbolS *) NULL)
+ {
+ if (symbol_get_tc (sym)->symbol_class == -1)
+ symbol_get_tc (sym)->symbol_class = symbol_get_tc (ppc_current_csect)->symbol_class;
+
+ symbol_remove (sym, &symbol_rootP, &symbol_lastP);
+ symbol_append (sym, symbol_get_tc (ppc_current_csect)->within,
+ &symbol_rootP, &symbol_lastP);
+ symbol_get_tc (ppc_current_csect)->within = sym;
+ symbol_get_tc (sym)->within = ppc_current_csect;
+ }
+#endif
+
+#ifdef OBJ_ELF
+ dwarf2_emit_label (sym);
+#endif
+}