mirror of
https://github.com/frida/tinycc
synced 2024-12-24 22:16:49 +03:00
tccasm: Implement .set sym, expr
That, as well as "sym = expr", if expr contains symbols. Slightly tricky because a definition from .set is overridable, whereas proper definitions aren't. This doesn't yet allow using this for override tricks from C and global asm blocks because the symbol tables from C and asm are separate.
This commit is contained in:
parent
34fc6435ee
commit
c4edfb4e08
65
tccasm.c
65
tccasm.c
@ -64,7 +64,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
||||
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;
|
||||
sym->type.t = VT_STATIC | VT_VOID | VT_EXTERN;
|
||||
}
|
||||
}
|
||||
pe->v = 0;
|
||||
@ -123,7 +123,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
||||
if (!sym) {
|
||||
sym = label_push(&s1->asm_labels, tok, 0);
|
||||
/* NOTE: by default, the symbol is global */
|
||||
sym->type.t = VT_VOID;
|
||||
sym->type.t = VT_VOID | VT_EXTERN;
|
||||
}
|
||||
if (sym->r == SHN_ABS) {
|
||||
/* if absolute symbol, no need to put a symbol value */
|
||||
@ -317,14 +317,17 @@ ST_FUNC int asm_int_expr(TCCState *s1)
|
||||
|
||||
/* 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,
|
||||
static Sym* 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) {
|
||||
/* A VT_EXTERN symbol, even if it has a section is considered
|
||||
overridable. This is how we "define" .set targets. Real
|
||||
definitions won't have VT_EXTERN set. */
|
||||
if (sym->r && !(sym->type.t & VT_EXTERN)) {
|
||||
/* the label is already defined */
|
||||
if (!is_local) {
|
||||
tcc_error("assembler label '%s' already defined",
|
||||
@ -337,15 +340,34 @@ static void asm_new_label1(TCCState *s1, int label, int is_local,
|
||||
} else {
|
||||
new_label:
|
||||
sym = label_push(&s1->asm_labels, label, 0);
|
||||
sym->type.t = VT_STATIC | VT_VOID;
|
||||
/* If we need a symbol to hold a value, mark it as
|
||||
tentative only (for .set). If this is for a real label
|
||||
we'll remove VT_EXTERN. */
|
||||
sym->type.t = VT_STATIC | VT_VOID | VT_EXTERN;
|
||||
}
|
||||
sym->r = sh_num;
|
||||
sym->jnext = value;
|
||||
return sym;
|
||||
}
|
||||
|
||||
static void asm_new_label(TCCState *s1, int label, int is_local)
|
||||
static Sym* asm_new_label(TCCState *s1, int label, int is_local)
|
||||
{
|
||||
asm_new_label1(s1, label, is_local, cur_text_section->sh_num, ind);
|
||||
return asm_new_label1(s1, label, is_local, cur_text_section->sh_num, ind);
|
||||
}
|
||||
|
||||
/* Set the value of LABEL to that of some expression (possibly
|
||||
involving other symbols). LABEL can be overwritten later still. */
|
||||
static Sym* set_symbol(TCCState *s1, int label)
|
||||
{
|
||||
Sym *sym;
|
||||
long n;
|
||||
ExprValue e;
|
||||
next();
|
||||
asm_expr(s1, &e);
|
||||
n = e.v;
|
||||
if (e.sym)
|
||||
n += e.sym->jnext;
|
||||
return asm_new_label1(s1, label, 0, e.sym ? e.sym->r : SHN_ABS, n);
|
||||
}
|
||||
|
||||
static void asm_free_labels(TCCState *st)
|
||||
@ -356,6 +378,7 @@ static void asm_free_labels(TCCState *st)
|
||||
for(s = st->asm_labels; s != NULL; s = s1) {
|
||||
s1 = s->prev;
|
||||
/* define symbol value in object file */
|
||||
s->type.t &= ~VT_EXTERN;
|
||||
if (s->r) {
|
||||
if (s->r == SHN_ABS)
|
||||
sec = SECTION_ABS;
|
||||
@ -608,6 +631,15 @@ static void asm_parse_directive(TCCState *s1)
|
||||
goto zero_pad;
|
||||
}
|
||||
break;
|
||||
case TOK_ASMDIR_set:
|
||||
next();
|
||||
tok1 = tok;
|
||||
next();
|
||||
/* Also accept '.set stuff', but don't do anything with this.
|
||||
It's used in GAS to set various features like '.set mips16'. */
|
||||
if (tok == ',')
|
||||
set_symbol(s1, tok1);
|
||||
break;
|
||||
case TOK_ASMDIR_globl:
|
||||
case TOK_ASMDIR_global:
|
||||
case TOK_ASMDIR_weak:
|
||||
@ -620,7 +652,7 @@ static void asm_parse_directive(TCCState *s1)
|
||||
sym = label_find(tok);
|
||||
if (!sym) {
|
||||
sym = label_push(&s1->asm_labels, tok, 0);
|
||||
sym->type.t = VT_VOID;
|
||||
sym->type.t = VT_VOID | VT_EXTERN;
|
||||
}
|
||||
if (tok1 != TOK_ASMDIR_hidden)
|
||||
sym->type.t &= ~VT_STATIC;
|
||||
@ -743,7 +775,7 @@ static void asm_parse_directive(TCCState *s1)
|
||||
sym = label_find(tok);
|
||||
if (!sym) {
|
||||
sym = label_push(&s1->asm_labels, tok, 0);
|
||||
sym->type.t = VT_VOID;
|
||||
sym->type.t = VT_VOID | VT_EXTERN;
|
||||
}
|
||||
|
||||
next();
|
||||
@ -875,6 +907,7 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess)
|
||||
} else if (tok >= TOK_ASMDIR_FIRST && tok <= TOK_ASMDIR_LAST) {
|
||||
asm_parse_directive(s1);
|
||||
} else if (tok == TOK_PPNUM) {
|
||||
Sym *sym;
|
||||
const char *p;
|
||||
int n;
|
||||
p = tokc.str.data;
|
||||
@ -882,7 +915,9 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess)
|
||||
if (*p != '\0')
|
||||
expect("':'");
|
||||
/* new local label */
|
||||
asm_new_label(s1, asm_get_local_label_name(s1, n), 1);
|
||||
sym = asm_new_label(s1, asm_get_local_label_name(s1, n), 1);
|
||||
/* Remove the marker for tentative definitions. */
|
||||
sym->type.t &= ~VT_EXTERN;
|
||||
next();
|
||||
skip(':');
|
||||
goto redo;
|
||||
@ -898,18 +933,16 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess)
|
||||
sym = label_find(opcode);
|
||||
if (!sym) {
|
||||
sym = label_push(&s1->asm_labels, opcode, 0);
|
||||
sym->type.t = VT_VOID;
|
||||
sym->type.t = VT_VOID | VT_EXTERN;
|
||||
}
|
||||
}
|
||||
/* new label */
|
||||
asm_new_label(s1, opcode, 0);
|
||||
sym = asm_new_label(s1, opcode, 0);
|
||||
sym->type.t &= ~VT_EXTERN;
|
||||
next();
|
||||
goto redo;
|
||||
} else if (tok == '=') {
|
||||
int n;
|
||||
next();
|
||||
n = asm_int_expr(s1);
|
||||
asm_new_label1(s1, opcode, 0, SHN_ABS, n);
|
||||
set_symbol(s1, opcode);
|
||||
goto redo;
|
||||
} else {
|
||||
asm_opcode(s1, opcode);
|
||||
|
1
tcctok.h
1
tcctok.h
@ -308,6 +308,7 @@
|
||||
DEF_ASMDIR(align)
|
||||
DEF_ASMDIR(balign)
|
||||
DEF_ASMDIR(p2align)
|
||||
DEF_ASMDIR(set)
|
||||
DEF_ASMDIR(skip)
|
||||
DEF_ASMDIR(space)
|
||||
DEF_ASMDIR(string)
|
||||
|
@ -824,6 +824,17 @@ nop
|
||||
.skip (-((4b-3b) > 0) * 2) , 0x90
|
||||
.popsection
|
||||
|
||||
.globl overrideme
|
||||
.weak overrideme
|
||||
nop
|
||||
.globl notimplemented
|
||||
notimplemented:
|
||||
ret
|
||||
.set overrideme, notimplemented
|
||||
overrideme = notimplemented
|
||||
overrideme:
|
||||
ret
|
||||
|
||||
movd %esi, %mm1
|
||||
movd %edi, %xmm2
|
||||
movd (%ebx), %mm3
|
||||
|
Loading…
Reference in New Issue
Block a user