1
0
Fork 0

Fix Extended Asm ignored constraints

This commit fixes the case where the register of for the Extended Asm
input or output is known. Before this commit, the following case:

  register long __a0 asm ("a0") = one;
  asm volatile (
       "ecall\n\t"
       : "+r" (__a0) // NOTE the +r here
  );

Didn't treat `a0` as an input+output register (+ contraint) as the code
skipped the constraint processing when the register was already chosen
(instead of allocated later).

This issue comes from f081acbfba, that was
taken as a reference in every other Extended Assembler implementation.
This commit is contained in:
Ekaitz Zarraga 2024-04-15 16:21:39 +02:00
parent 4944f509c3
commit 0703df1a6a
3 changed files with 18 additions and 8 deletions

View File

@ -3075,7 +3075,6 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
tcc_error
("asm regvar requests register that's taken already");
reg = op->reg;
goto reg_found;
}
try_next:
c = *str++;
@ -3095,7 +3094,9 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
case 'r': // general-purpose register
case 'p': // loadable/storable address
/* any general register */
for (reg = 0; reg <= 8; reg++) {
if ((reg = op->reg) >= 0)
goto reg_found;
else for (reg = 0; reg <= 8; reg++) {
if (!is_reg_allocated(reg))
goto reg_found;
}

View File

@ -1342,7 +1342,6 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
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++;
@ -1385,12 +1384,17 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
case 'D':
reg = 7;
alloc_reg:
if (op->reg >= 0 && reg != op->reg)
goto try_next;
if (is_reg_allocated(reg))
goto try_next;
goto reg_found;
case 'q':
/* eax, ebx, ecx or edx */
for(reg = 0; reg < 4; reg++) {
if (op->reg >= 0) {
if ((reg = op->reg) < 4)
goto reg_found;
} else for(reg = 0; reg < 4; reg++) {
if (!is_reg_allocated(reg))
goto reg_found;
}
@ -1399,7 +1403,9 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
case 'R':
case 'p': /* A general address, for x86(64) any register is acceptable*/
/* any general register */
for(reg = 0; reg < 8; reg++) {
if ((reg = op->reg) >= 0)
goto reg_found;
else for(reg = 0; reg < 8; reg++) {
if (!is_reg_allocated(reg))
goto reg_found;
}

View File

@ -1720,7 +1720,6 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
tcc_error
("asm regvar requests register that's taken already");
reg = op->reg;
goto reg_found;
}
try_next:
c = *str++;
@ -1739,7 +1738,9 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
case 'p': // loadable/storable address
/* any general register */
/* From a0 to a7 */
for (reg = 10; reg <= 18; reg++) {
if ((reg = op->reg) >= 0)
goto reg_found;
else for (reg = 10; reg <= 18; reg++) {
if (!is_reg_allocated(reg))
goto reg_found;
}
@ -1753,7 +1754,9 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
case 'f': // floating pont register
/* floating point register */
/* From fa0 to fa7 */
for (reg = 42; reg <= 50; reg++) {
if ((reg = op->reg) >= 0)
goto reg_found;
else for (reg = 42; reg <= 50; reg++) {
if (!is_reg_allocated(reg))
goto reg_found;
}