void label_union (Label *a, Label *b) { Label *root_a, *root_b; root_a = label_find (a); root_b = label_find (b); if (root_a->index < root_b->index) { b->parent = root_a; } else { a->parent = root_b; } }
/* NOTE: the same name space as C labels is used to avoid using too much memory when storing labels in TokenStrings */ static void asm_new_label1(TCCState *s1, int label, int is_local, int sh_num, int value) { Sym *sym; sym = label_find(label); if (sym) { if (sym->r) { /* the label is already defined */ if (!is_local) { tcc_error("assembler label '%s' already defined", get_tok_str(label, NULL)); } else { /* redefinition of local labels is possible */ goto new_label; } } } else { new_label: sym = label_push(&s1->asm_labels, label, 0); sym->type.t = VT_STATIC | VT_VOID; } sym->r = sh_num; sym->jnext = value; }
Label * label_find (Label *label) { Label *parent; g_return_val_if_fail (label != NULL, NULL); parent = label->parent; if (parent == label) return parent; else return label_find (parent); }
static void asm_expr_unary(TCCState *s1, ExprValue *pe) { Sym *sym; int op, n, label; const char *p; switch(tok) { case TOK_PPNUM: p = tokc.cstr->data; n = strtoul(p, (char **)&p, 0); if (*p == 'b' || *p == 'f') { /* backward or forward label */ label = asm_get_local_label_name(s1, n); sym = label_find(label); if (*p == 'b') { /* backward : find the last corresponding defined label */ if (sym && sym->r == 0) sym = sym->prev_tok; if (!sym) tcc_error("local label '%d' not found backward", n); } else { /* forward */ if (!sym || sym->r) { /* if the last label is defined, then define a new one */ sym = label_push(&s1->asm_labels, label, 0); sym->type.t = VT_STATIC | VT_VOID; } } pe->v = 0; pe->sym = sym; } else if (*p == '\0') { pe->v = n; pe->sym = NULL; } else { tcc_error("invalid number syntax"); } next(); break; case '+': next(); asm_expr_unary(s1, pe); break; case '-': case '~': op = tok; next(); asm_expr_unary(s1, pe); if (pe->sym) tcc_error("invalid operation with label"); if (op == '-') pe->v = -pe->v; else pe->v = ~pe->v; break; case TOK_CCHAR: case TOK_LCHAR: pe->v = tokc.i; pe->sym = NULL; next(); break; case '(': next(); asm_expr(s1, pe); skip(')'); break; default: if (tok >= TOK_IDENT) { /* label case : if the label was not found, add one */ sym = label_find(tok); if (!sym) { sym = label_push(&s1->asm_labels, tok, 0); /* NOTE: by default, the symbol is global */ sym->type.t = VT_VOID; } if (sym->r == SHN_ABS) { /* if absolute symbol, no need to put a symbol value */ pe->v = sym->jnext; pe->sym = NULL; } else { pe->v = 0; pe->sym = sym; } next(); } else { tcc_error("bad expression syntax [%s]", get_tok_str(tok, &tokc)); } break; } }