History

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.

Michael Matz committed 10 years ago

Commit f081acb1 parent 3bc9c324 files · +58 −6Browse files

Unified · Split

4 files
  1. i386-asm.c +33 −0
  2. tcc.h +5 −3
  3. tccgen.c +17 −3
  4. tests/tcctest.c +3 −0
i386-asm.c+33−0
@@ -1185,6 +1185,28 @@ static const char *skip_constraint_modifiers(const char *p) · 1184 unmodified lines
11851185 return p;
11861186 }
11871187
1188+/* If T (a token) is of the form "%reg" returns the register
1189+ number and type, otherwise return -1. */
1190+ST_FUNC int asm_parse_regvar (int t)
1191+{
1192+ const char *s;
1193+ Operand op;
1194+ if (t < TOK_IDENT)
1195+ return -1;
1196+ s = table_ident[t - TOK_IDENT]->str;
1197+ if (s[0] != '%')
1198+ return -1;
1199+ t = tok_alloc(s+1, strlen(s)-1)->tok;
1200+ unget_tok(t);
1201+ unget_tok('%');
1202+ parse_operand(tcc_state, &op);
1203+ /* Accept only integer regs for now. */
1204+ if (op.type & OP_REG)
1205+ return op.reg;
1206+ else
1207+ return -1;
1208+}
1209+
11881210 #define REG_OUT_MASK 0x01
11891211 #define REG_IN_MASK 0x02
11901212
@@ -1227,6 +1249,11 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands, · 36 unmodified lines
12271249 tcc_error("cannot reference twice the same operand");
12281250 operands[k].input_index = i;
12291251 op->priority = 5;
1252+ } else if ((op->vt->r & VT_VALMASK) == VT_LOCAL
1253+ && op->vt->sym
1254+ && (reg = op->vt->sym->r & VT_VALMASK) < VT_CONST) {
1255+ op->priority = 1;
1256+ op->reg = reg;
12301257 } else {
12311258 op->priority = constraint_priority(str);
12321259 }
@@ -1274,6 +1301,12 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands, · 41 unmodified lines
12741301 } else {
12751302 reg_mask = REG_IN_MASK;
12761303 }
1304+ if (op->reg >= 0) {
1305+ if (is_reg_allocated(op->reg))
1306+ tcc_error("asm regvar requests register that's taken already");
1307+ reg = op->reg;
1308+ goto reg_found;
1309+ }
12771310 try_next:
12781311 c = *str++;
12791312 switch(c) {
tcc.h+5−3
@@ -372,7 +372,8 @@ typedef struct SValue { · 371 unmodified lines
372372 unsigned short r2; /* second register, used for 'long long'
373373 type. If not used, set to VT_CONST */
374374 CValue c; /* constant, if VT_CONST */
375− struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
375+ struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST), or if
376+ result of unary() for an identifier. */
376377 } SValue;
377378
378379 struct Attribute {
@@ -407,7 +408,7 @@ typedef struct Sym { · 28 unmodified lines
407408 int scope; /* scope level for locals */
408409 };
409410 union {
410− long r; /* associated register */
411+ long r; /* associated register or VT_CONST/VT_LOCAL and LVAL type */
411412 struct Attribute a;
412413 };
413414 union {
@@ -416,7 +417,7 @@ typedef struct Sym { · 2 unmodified lines
416417 };
417418 CType type; /* associated type */
418419 union {
419− struct Sym *next; /* next related symbol */
420+ struct Sym *next; /* next related symbol (for fields and anoms) */
420421 long jnext; /* next jump label */
421422 };
422423 struct Sym *prev; /* prev symbol in stack */
@@ -1542,6 +1543,7 @@ ST_FUNC void gen_expr32(ExprValue *pe); · 1119 unmodified lines
15421543 ST_FUNC void gen_expr64(ExprValue *pe);
15431544 #endif
15441545 ST_FUNC void asm_opcode(TCCState *s1, int opcode);
1546+ST_FUNC int asm_parse_regvar(int t);
15451547 ST_FUNC void asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg);
15461548 ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier);
15471549 ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);
tccgen.c+17−3
@@ -386,7 +386,7 @@ ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, long c) · 385 unmodified lines
386386 Sym *s;
387387
388388 s = sym_malloc();
389− s->asm_label = 0;
389+ s->scope = 0;
390390 s->v = v;
391391 s->type.t = t;
392392 s->type.ref = NULL;
@@ -577,6 +577,7 @@ static void vsetc(CType *type, int r, CValue *vc) · 184 unmodified lines
577577 vtop->r = r;
578578 vtop->r2 = VT_CONST;
579579 vtop->c = *vc;
580+ vtop->sym = NULL;
580581 }
581582
582583 /* push constant of type "type" with useless value */
@@ -4599,11 +4600,17 @@ ST_FUNC void unary(void) · 4016 unmodified lines
45994600 r = VT_SYM | VT_CONST;
46004601 } else {
46014602 r = s->r;
4603+ /* A symbol that has a register is a local register variable,
4604+ which starts out as VT_LOCAL value. */
4605+ if ((r & VT_VALMASK) < VT_CONST)
4606+ r = (r & ~VT_VALMASK) | VT_LOCAL;
46024607 }
46034608 vset(&s->type, r, s->c);
4604− /* if forward reference, we must point to s */
4609+ /* Point to s as backpointer (even without r&VT_SYM).
4610+ Will be used by at least the x86 inline asm parser for
4611+ regvars. */
4612+ vtop->sym = s;
46054613 if (vtop->r & VT_SYM) {
4606− vtop->sym = s;
46074614 vtop->c.i = 0;
46084615 }
46094616 break;
@@ -6462,6 +6469,13 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 1852 unmodified lines
64626469 #endif
64636470 if (v) {
64646471 /* local variable */
6472+#ifdef CONFIG_TCC_ASM
6473+ if (ad->asm_label) {
6474+ int reg = asm_parse_regvar(ad->asm_label);
6475+ if (reg >= 0)
6476+ r = (r & ~VT_VALMASK) | reg;
6477+ }
6478+#endif
64656479 sym_push(v, type, r, addr);
64666480 } else {
64676481 /* push local reference */
tests/tcctest.c+3−0
@@ -2939,6 +2939,7 @@ void asm_test(void) · 2938 unmodified lines
29392939 #ifdef BOOL_ISOC99
29402940 _Bool somebool;
29412941 #endif
2942+ register int regvar asm("%esi");
29422943
29432944 printf("inline asm:\n");
29442945
@@ -3001,6 +3002,8 @@ void asm_test(void) · 56 unmodified lines
30013002 val = 44;
30023003 fancy_copy2 (&val, &val2);
30033004 printf ("fancycpy2(%d)=%d\n", val, val2);
3005+ asm volatile ("mov $0x4243, %%esi" : "=r" (regvar));
3006+ printf ("regvar=%x\n", regvar);
30043007 return;
30053008 label1:
30063009 goto label2;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t