diff options
| author | Michael Matz <matz@suse.de> | 2016-10-06 04:05:30 +0200 |
|---|---|---|
| committer | Michael Matz <matz@suse.de> | 2016-12-15 17:47:13 +0100 |
| commit | f081acbfba84ffdf1e479f932906bf10f88cd1c2 (patch) | |
| tree | 16f39dd9b65312bc83bb5b3d3e462b6242630b9a /tccgen.c | |
| parent | 3bc9c325c5fa754043986cc70ff2af45c2196c38 (diff) | |
| download | tinycc-f081acbfba84ffdf1e479f932906bf10f88cd1c2.tar.gz tinycc-f081acbfba84ffdf1e479f932906bf10f88cd1c2.tar.bz2 | |
Support local register variables
Similar to GCC a local asm register variable enforces the use of a
specified register in asm operands (and doesn't otherwise
matter). Works only if the variable is directly mentioned as
operand. For that we now generally store a backpointer from
an SValue to a Sym when the SValue was the result of unary()
parsing a symbol identifier.
Diffstat (limited to 'tccgen.c')
| -rw-r--r-- | tccgen.c | 20 |
1 files changed, 17 insertions, 3 deletions
@@ -386,7 +386,7 @@ ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, long c) Sym *s; s = sym_malloc(); - s->asm_label = 0; + s->scope = 0; s->v = v; s->type.t = t; s->type.ref = NULL; @@ -577,6 +577,7 @@ static void vsetc(CType *type, int r, CValue *vc) vtop->r = r; vtop->r2 = VT_CONST; vtop->c = *vc; + vtop->sym = NULL; } /* push constant of type "type" with useless value */ @@ -4599,11 +4600,17 @@ ST_FUNC void unary(void) r = VT_SYM | VT_CONST; } else { r = s->r; + /* A symbol that has a register is a local register variable, + which starts out as VT_LOCAL value. */ + if ((r & VT_VALMASK) < VT_CONST) + r = (r & ~VT_VALMASK) | VT_LOCAL; } vset(&s->type, r, s->c); - /* if forward reference, we must point to s */ + /* Point to s as backpointer (even without r&VT_SYM). + Will be used by at least the x86 inline asm parser for + regvars. */ + vtop->sym = s; if (vtop->r & VT_SYM) { - vtop->sym = s; vtop->c.i = 0; } break; @@ -6462,6 +6469,13 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, #endif if (v) { /* local variable */ +#ifdef CONFIG_TCC_ASM + if (ad->asm_label) { + int reg = asm_parse_regvar(ad->asm_label); + if (reg >= 0) + r = (r & ~VT_VALMASK) | reg; + } +#endif sym_push(v, type, r, addr); } else { /* push local reference */ |
