From f081acbfba84ffdf1e479f932906bf10f88cd1c2 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Thu, 6 Oct 2016 04:05:30 +0200 Subject: 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. --- i386-asm.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'i386-asm.c') diff --git a/i386-asm.c b/i386-asm.c index 16b2e91..a62a4cf 100644 --- a/i386-asm.c +++ b/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) { -- cgit v1.3.1