aboutsummaryrefslogtreecommitdiff
path: root/tccgen.c
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2016-10-06 04:05:30 +0200
committerMichael Matz <matz@suse.de>2016-12-15 17:47:13 +0100
commitf081acbfba84ffdf1e479f932906bf10f88cd1c2 (patch)
tree16f39dd9b65312bc83bb5b3d3e462b6242630b9a /tccgen.c
parent3bc9c325c5fa754043986cc70ff2af45c2196c38 (diff)
downloadtinycc-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.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/tccgen.c b/tccgen.c
index f7b7c2d..5c2acf8 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -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 */