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.
This commit is contained in:
33
i386-asm.c
33
i386-asm.c
@ -1185,6 +1185,28 @@ static const char *skip_constraint_modifiers(const char *p)
|
||||
return p;
|
||||
}
|
||||
|
||||
/* If T (a token) is of the form "%reg" returns the register
|
||||
number and type, otherwise return -1. */
|
||||
ST_FUNC int asm_parse_regvar (int t)
|
||||
{
|
||||
const char *s;
|
||||
Operand op;
|
||||
if (t < TOK_IDENT)
|
||||
return -1;
|
||||
s = table_ident[t - TOK_IDENT]->str;
|
||||
if (s[0] != '%')
|
||||
return -1;
|
||||
t = tok_alloc(s+1, strlen(s)-1)->tok;
|
||||
unget_tok(t);
|
||||
unget_tok('%');
|
||||
parse_operand(tcc_state, &op);
|
||||
/* Accept only integer regs for now. */
|
||||
if (op.type & OP_REG)
|
||||
return op.reg;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define REG_OUT_MASK 0x01
|
||||
#define REG_IN_MASK 0x02
|
||||
|
||||
@ -1227,6 +1249,11 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
||||
tcc_error("cannot reference twice the same operand");
|
||||
operands[k].input_index = i;
|
||||
op->priority = 5;
|
||||
} else if ((op->vt->r & VT_VALMASK) == VT_LOCAL
|
||||
&& op->vt->sym
|
||||
&& (reg = op->vt->sym->r & VT_VALMASK) < VT_CONST) {
|
||||
op->priority = 1;
|
||||
op->reg = reg;
|
||||
} else {
|
||||
op->priority = constraint_priority(str);
|
||||
}
|
||||
@ -1274,6 +1301,12 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
||||
} else {
|
||||
reg_mask = REG_IN_MASK;
|
||||
}
|
||||
if (op->reg >= 0) {
|
||||
if (is_reg_allocated(op->reg))
|
||||
tcc_error("asm regvar requests register that's taken already");
|
||||
reg = op->reg;
|
||||
goto reg_found;
|
||||
}
|
||||
try_next:
|
||||
c = *str++;
|
||||
switch(c) {
|
||||
|
||||
Reference in New Issue
Block a user