Tabs vs spaces

This commit is contained in:
2026-01-19 14:16:44 +01:00
parent 0b23707041
commit fa42b20136

View File

@@ -288,18 +288,18 @@ static void gen_modrm_impl(int op_reg, int r, Sym *sym, int c, int is_got)
op_reg = REG_VALUE(op_reg) << 3; op_reg = REG_VALUE(op_reg) << 3;
if ((r & VT_VALMASK) == VT_CONST) { if ((r & VT_VALMASK) == VT_CONST) {
/* constant memory reference */ /* constant memory reference */
if (!(r & VT_SYM)) { if (!(r & VT_SYM)) {
/* Absolute memory reference */ /* Absolute memory reference */
o(0x04 | op_reg); /* [sib] | destreg */ o(0x04 | op_reg); /* [sib] | destreg */
oad(0x25, c); /* disp32 */ oad(0x25, c); /* disp32 */
} else { } else {
o(0x05 | op_reg); /* (%rip)+disp32 | destreg */ o(0x05 | op_reg); /* (%rip)+disp32 | destreg */
if (is_got) { if (is_got) {
gen_gotpcrel(r, sym, c); gen_gotpcrel(r, sym, c);
} else { } else {
gen_addrpc32(r, sym, c); gen_addrpc32(r, sym, c);
} }
} }
} else if ((r & VT_VALMASK) == VT_LOCAL) { } else if ((r & VT_VALMASK) == VT_LOCAL) {
/* currently, we use only ebp as base */ /* currently, we use only ebp as base */
if (c == (char)c) { if (c == (char)c) {
@@ -387,36 +387,36 @@ void load(int r, SValue *sv)
fr = get_reg(RC_INT); fr = get_reg(RC_INT);
load(fr, &v1); load(fr, &v1);
} }
if (fc != sv->c.i) { if (fc != sv->c.i) {
/* If the addends doesn't fit into a 32bit signed /* If the addends doesn't fit into a 32bit signed
we must use a 64bit move. We've checked above we must use a 64bit move. We've checked above
that this doesn't have a sym associated. */ that this doesn't have a sym associated. */
v1.type.t = VT_LLONG; v1.type.t = VT_LLONG;
v1.r = VT_CONST; v1.r = VT_CONST;
v1.c.i = sv->c.i; v1.c.i = sv->c.i;
fr = r; fr = r;
if (!(reg_classes[fr] & (RC_INT|RC_R11))) if (!(reg_classes[fr] & (RC_INT|RC_R11)))
fr = get_reg(RC_INT); fr = get_reg(RC_INT);
load(fr, &v1); load(fr, &v1);
fc = 0; fc = 0;
} }
ll = 0; ll = 0;
/* Like GCC we can load from small enough properly sized /* Like GCC we can load from small enough properly sized
structs and unions as well. structs and unions as well.
XXX maybe move to generic operand handling, but should XXX maybe move to generic operand handling, but should
occur only with asm, so tccasm.c might also be a better place */ occur only with asm, so tccasm.c might also be a better place */
if ((ft & VT_BTYPE) == VT_STRUCT) { if ((ft & VT_BTYPE) == VT_STRUCT) {
int align; int align;
switch (type_size(&sv->type, &align)) { switch (type_size(&sv->type, &align)) {
case 1: ft = VT_BYTE; break; case 1: ft = VT_BYTE; break;
case 2: ft = VT_SHORT; break; case 2: ft = VT_SHORT; break;
case 4: ft = VT_INT; break; case 4: ft = VT_INT; break;
case 8: ft = VT_LLONG; break; case 8: ft = VT_LLONG; break;
default: default:
tcc_error("invalid aggregate type for register load"); tcc_error("invalid aggregate type for register load");
break; break;
} }
} }
if ((ft & VT_BTYPE) == VT_FLOAT) { if ((ft & VT_BTYPE) == VT_FLOAT) {
b = 0x6e0f66; b = 0x6e0f66;
r = REG_VALUE(r); /* movd */ r = REG_VALUE(r); /* movd */
@@ -478,18 +478,18 @@ void load(int r, SValue *sv)
gen_modrm(r, VT_LOCAL, sv->sym, fc); gen_modrm(r, VT_LOCAL, sv->sym, fc);
} else if (v == VT_CMP) { } else if (v == VT_CMP) {
orex(0,r,0,0); orex(0,r,0,0);
if ((fc & ~0x100) != TOK_NE) if ((fc & ~0x100) != TOK_NE)
oad(0xb8 + REG_VALUE(r), 0); /* mov $0, r */ oad(0xb8 + REG_VALUE(r), 0); /* mov $0, r */
else else
oad(0xb8 + REG_VALUE(r), 1); /* mov $1, r */ oad(0xb8 + REG_VALUE(r), 1); /* mov $1, r */
if (fc & 0x100) if (fc & 0x100)
{ {
/* This was a float compare. If the parity bit is /* This was a float compare. If the parity bit is
set the result was unordered, meaning false for everything set the result was unordered, meaning false for everything
except TOK_NE, and true for TOK_NE. */ except TOK_NE, and true for TOK_NE. */
fc &= ~0x100; fc &= ~0x100;
o(0x037a + (REX_BASE(r) << 8)); o(0x037a + (REX_BASE(r) << 8));
} }
orex(0,r,0, 0x0f); /* setxx %br */ orex(0,r,0, 0x0f); /* setxx %br */
o(fc); o(fc);
o(0xc0 + REG_VALUE(r)); o(0xc0 + REG_VALUE(r));
@@ -623,7 +623,7 @@ static void gcall_or_jmp(int is_jmp)
{ {
int r; int r;
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
((vtop->r & VT_SYM) || (vtop->c.i-4) == (int)(vtop->c.i-4))) { ((vtop->r & VT_SYM) || (vtop->c.i-4) == (int)(vtop->c.i-4))) {
/* constant case */ /* constant case */
if (vtop->r & VT_SYM) { if (vtop->r & VT_SYM) {
/* relocation case */ /* relocation case */
@@ -875,8 +875,8 @@ void gfunc_call(int nb_args)
struct_size += size; struct_size += size;
} else { } else {
if (is_sse_float(vtop->type.t)) { if (is_sse_float(vtop->type.t)) {
if (tcc_state->nosse) if (tcc_state->nosse)
tcc_error("SSE disabled"); tcc_error("SSE disabled");
gv(RC_XMM0); /* only use one float register */ gv(RC_XMM0); /* only use one float register */
if (arg >= REGN) { if (arg >= REGN) {
/* movq %xmm0, j*8(%rsp) */ /* movq %xmm0, j*8(%rsp) */
@@ -994,8 +994,8 @@ void gfunc_prolog(CType *func_type)
if (reg_param_index < REGN) { if (reg_param_index < REGN) {
/* save arguments passed by register */ /* save arguments passed by register */
if ((bt == VT_FLOAT) || (bt == VT_DOUBLE)) { if ((bt == VT_FLOAT) || (bt == VT_DOUBLE)) {
if (tcc_state->nosse) if (tcc_state->nosse)
tcc_error("SSE disabled"); tcc_error("SSE disabled");
o(0xd60f66); /* movq */ o(0xd60f66); /* movq */
gen_modrm(reg_param_index, VT_LOCAL, NULL, addr); gen_modrm(reg_param_index, VT_LOCAL, NULL, addr);
} else { } else {
@@ -1252,20 +1252,20 @@ void gfunc_call(int nb_args)
mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, &reg_count); mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, &reg_count);
if (mode == x86_64_mode_sse && nb_sse_args + reg_count <= 8) { if (mode == x86_64_mode_sse && nb_sse_args + reg_count <= 8) {
nb_sse_args += reg_count; nb_sse_args += reg_count;
onstack[i] = 0; onstack[i] = 0;
} else if (mode == x86_64_mode_integer && nb_reg_args + reg_count <= REGN) { } else if (mode == x86_64_mode_integer && nb_reg_args + reg_count <= REGN) {
nb_reg_args += reg_count; nb_reg_args += reg_count;
onstack[i] = 0; onstack[i] = 0;
} else if (mode == x86_64_mode_none) { } else if (mode == x86_64_mode_none) {
onstack[i] = 0; onstack[i] = 0;
} else { } else {
if (align == 16 && (stack_adjust &= 15)) { if (align == 16 && (stack_adjust &= 15)) {
onstack[i] = 2; onstack[i] = 2;
stack_adjust = 0; stack_adjust = 0;
} else } else
onstack[i] = 1; onstack[i] = 1;
stack_adjust += size; stack_adjust += size;
} }
} }
if (nb_sse_args && tcc_state->nosse) if (nb_sse_args && tcc_state->nosse)
@@ -1283,71 +1283,71 @@ void gfunc_call(int nb_args)
args_size = 0; args_size = 0;
stack_adjust &= 15; stack_adjust &= 15;
for (i = 0; i < nb_args;) { for (i = 0; i < nb_args;) {
mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, &reg_count); mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, &reg_count);
if (!onstack[i]) { if (!onstack[i]) {
++i; ++i;
continue; continue;
}
/* Possibly adjust stack to align SSE boundary. We're processing
args from right to left while allocating happens left to right
(stack grows down), so the adjustment needs to happen _after_
an argument that requires it. */
if (stack_adjust) {
o(0x50); /* push %rax; aka sub $8,%rsp */
args_size += 8;
stack_adjust = 0;
} }
if (onstack[i] == 2) /* Possibly adjust stack to align SSE boundary. We're processing
stack_adjust = 1; args from right to left while allocating happens left to right
(stack grows down), so the adjustment needs to happen _after_
an argument that requires it. */
if (stack_adjust) {
o(0x50); /* push %rax; aka sub $8,%rsp */
args_size += 8;
stack_adjust = 0;
}
if (onstack[i] == 2)
stack_adjust = 1;
vrotb(i+1); vrotb(i+1);
switch (vtop->type.t & VT_BTYPE) { switch (vtop->type.t & VT_BTYPE) {
case VT_STRUCT: case VT_STRUCT:
/* allocate the necessary size on stack */ /* allocate the necessary size on stack */
o(0x48); o(0x48);
oad(0xec81, size); /* sub $xxx, %rsp */ oad(0xec81, size); /* sub $xxx, %rsp */
/* generate structure store */ /* generate structure store */
r = get_reg(RC_INT); r = get_reg(RC_INT);
orex(1, r, 0, 0x89); /* mov %rsp, r */ orex(1, r, 0, 0x89); /* mov %rsp, r */
o(0xe0 + REG_VALUE(r)); o(0xe0 + REG_VALUE(r));
vset(&vtop->type, r | VT_LVAL, 0); vset(&vtop->type, r | VT_LVAL, 0);
vswap(); vswap();
vstore(); vstore();
break; break;
case VT_LDOUBLE: case VT_LDOUBLE:
gv(RC_ST0); gv(RC_ST0);
oad(0xec8148, size); /* sub $xxx, %rsp */ oad(0xec8148, size); /* sub $xxx, %rsp */
o(0x7cdb); /* fstpt 0(%rsp) */ o(0x7cdb); /* fstpt 0(%rsp) */
g(0x24); g(0x24);
g(0x00); g(0x00);
break; break;
case VT_FLOAT: case VT_FLOAT:
case VT_DOUBLE: case VT_DOUBLE:
assert(mode == x86_64_mode_sse); assert(mode == x86_64_mode_sse);
r = gv(RC_FLOAT); r = gv(RC_FLOAT);
o(0x50); /* push $rax */ o(0x50); /* push $rax */
/* movq %xmmN, (%rsp) */ /* movq %xmmN, (%rsp) */
o(0xd60f66); o(0xd60f66);
o(0x04 + REG_VALUE(r)*8); o(0x04 + REG_VALUE(r)*8);
o(0x24); o(0x24);
break; break;
default: default:
assert(mode == x86_64_mode_integer); assert(mode == x86_64_mode_integer);
/* simple type */ /* simple type */
/* XXX: implicit cast ? */ /* XXX: implicit cast ? */
r = gv(RC_INT); r = gv(RC_INT);
orex(0,r,0,0x50 + REG_VALUE(r)); /* push r */ orex(0,r,0,0x50 + REG_VALUE(r)); /* push r */
break; break;
} }
args_size += size; args_size += size;
vpop(); vpop();
--nb_args; --nb_args;
onstack++; onstack++;
} }
/* XXX This should be superfluous. */ /* XXX This should be superfluous. */
@@ -1465,14 +1465,14 @@ void gfunc_prolog(CType *func_type)
case x86_64_mode_integer: case x86_64_mode_integer:
if (seen_reg_num + reg_count > REGN) if (seen_reg_num + reg_count > REGN)
goto stack_arg; goto stack_arg;
seen_reg_num += reg_count; seen_reg_num += reg_count;
break; break;
case x86_64_mode_sse: case x86_64_mode_sse:
if (seen_sse_num + reg_count > 8) if (seen_sse_num + reg_count > 8)
goto stack_arg; goto stack_arg;
seen_sse_num += reg_count; seen_sse_num += reg_count;
break; break;
} }
} }
@@ -1491,10 +1491,10 @@ void gfunc_prolog(CType *func_type)
/* save all register passing arguments */ /* save all register passing arguments */
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
loc -= 16; loc -= 16;
if (!tcc_state->nosse) { if (!tcc_state->nosse) {
o(0xd60f66); /* movq */ o(0xd60f66); /* movq */
gen_modrm(7 - i, VT_LOCAL, NULL, loc); gen_modrm(7 - i, VT_LOCAL, NULL, loc);
} }
/* movq $0, loc+8(%rbp) */ /* movq $0, loc+8(%rbp) */
o(0x85c748); o(0x85c748);
gen_le32(loc + 8); gen_le32(loc + 8);
@@ -1524,8 +1524,8 @@ void gfunc_prolog(CType *func_type)
mode = classify_x86_64_arg(type, NULL, &size, &align, &reg_count); mode = classify_x86_64_arg(type, NULL, &size, &align, &reg_count);
switch (mode) { switch (mode) {
case x86_64_mode_sse: case x86_64_mode_sse:
if (tcc_state->nosse) if (tcc_state->nosse)
tcc_error("SSE disabled but floating point arguments used"); tcc_error("SSE disabled but floating point arguments used");
if (sse_param_index + reg_count <= 8) { if (sse_param_index + reg_count <= 8) {
/* save arguments passed by register */ /* save arguments passed by register */
loc -= reg_count * 8; loc -= reg_count * 8;
@@ -1565,7 +1565,7 @@ void gfunc_prolog(CType *func_type)
} }
break; break;
} }
default: break; /* nothing to be done for x86_64_mode_none */ default: break; /* nothing to be done for x86_64_mode_none */
} }
sym_push(sym->v & ~SYM_FIELD, type, sym_push(sym->v & ~SYM_FIELD, type,
VT_LOCAL | VT_LVAL, param_addr); VT_LOCAL | VT_LVAL, param_addr);
@@ -1577,8 +1577,8 @@ void gfunc_prolog(CType *func_type)
func_bound_offset = lbounds_section->data_offset; func_bound_offset = lbounds_section->data_offset;
func_bound_ind = ind; func_bound_ind = ind;
oad(0xb8, 0); /* lbound section pointer */ oad(0xb8, 0); /* lbound section pointer */
o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */ o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */
oad(0xb8, 0); /* call to function */ oad(0xb8, 0); /* call to function */
} }
#endif #endif
} }
@@ -1590,7 +1590,7 @@ void gfunc_epilog(void)
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check if (tcc_state->do_bounds_check
&& func_bound_offset != lbounds_section->data_offset) && func_bound_offset != lbounds_section->data_offset)
{ {
addr_t saved_ind; addr_t saved_ind;
addr_t *bounds_ptr; addr_t *bounds_ptr;
@@ -1662,25 +1662,25 @@ ST_FUNC void gtst_addr(int inv, int a)
{ {
int v = vtop->r & VT_VALMASK; int v = vtop->r & VT_VALMASK;
if (v == VT_CMP) { if (v == VT_CMP) {
inv ^= (vtop--)->c.i; inv ^= (vtop--)->c.i;
a -= ind + 2; a -= ind + 2;
if (a == (char)a) { if (a == (char)a) {
g(inv - 32); g(inv - 32);
g(a); g(a);
} else { } else {
g(0x0f); g(0x0f);
oad(inv - 16, a - 4); oad(inv - 16, a - 4);
} }
} else if ((v & ~1) == VT_JMP) { } else if ((v & ~1) == VT_JMP) {
if ((v & 1) != inv) { if ((v & 1) != inv) {
gjmp_addr(a); gjmp_addr(a);
gsym(vtop->c.i); gsym(vtop->c.i);
} else { } else {
gsym(vtop->c.i); gsym(vtop->c.i);
o(0x05eb); o(0x05eb);
gjmp_addr(a); gjmp_addr(a);
} }
vtop--; vtop--;
} }
} }
@@ -1693,24 +1693,24 @@ ST_FUNC int gtst(int inv, int t)
; ;
} else if (v == VT_CMP) { } else if (v == VT_CMP) {
/* fast case : can jump directly since flags are set */ /* fast case : can jump directly since flags are set */
if (vtop->c.i & 0x100) if (vtop->c.i & 0x100)
{ {
/* This was a float compare. If the parity flag is set /* This was a float compare. If the parity flag is set
the result was unordered. For anything except != this the result was unordered. For anything except != this
means false and we don't jump (anding both conditions). means false and we don't jump (anding both conditions).
For != this means true (oring both). For != this means true (oring both).
Take care about inverting the test. We need to jump Take care about inverting the test. We need to jump
to our target if the result was unordered and test wasn't NE, to our target if the result was unordered and test wasn't NE,
otherwise if unordered we don't want to jump. */ otherwise if unordered we don't want to jump. */
vtop->c.i &= ~0x100; vtop->c.i &= ~0x100;
if (inv == (vtop->c.i == TOK_NE)) if (inv == (vtop->c.i == TOK_NE))
o(0x067a); /* jp +6 */ o(0x067a); /* jp +6 */
else else
{ {
g(0x0f); g(0x0f);
t = gjmp2(0x8a, t); /* jp t */ t = gjmp2(0x8a, t); /* jp t */
} }
} }
g(0x0f); g(0x0f);
t = gjmp2((vtop->c.i - 16) ^ inv, t); t = gjmp2((vtop->c.i - 16) ^ inv, t);
} else if (v == VT_JMP || v == VT_JMPI) { } else if (v == VT_JMP || v == VT_JMPI) {