Alien-TinyCCx
view release on metacpan or search on metacpan
src/tccgen.c view on Meta::CPAN
/* if both pointers, then it must be the '-' op */
if (bt1 == VT_PTR && bt2 == VT_PTR) {
if (op != '-')
tcc_error("cannot use pointers here");
check_comparison_pointer_types(vtop - 1, vtop, op);
/* XXX: check that types are compatible */
if (vtop[-1].type.t & VT_VLA) {
vla_runtime_pointed_size(&vtop[-1].type);
} else {
vpushi(pointed_size(&vtop[-1].type));
}
vrott(3);
gen_opic(op);
/* set to integer type */
#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
vtop->type.t = VT_LLONG;
#else
vtop->type.t = VT_INT;
#endif
vswap();
gen_op(TOK_PDIV);
} else {
/* exactly one pointer : must be '+' or '-'. */
if (op != '-' && op != '+')
tcc_error("cannot use pointers here");
/* Put pointer as first operand */
if (bt2 == VT_PTR) {
vswap();
swap(&t1, &t2);
}
#if PTR_SIZE == 4
if ((vtop[0].type.t & VT_BTYPE) == VT_LLONG)
/* XXX: truncate here because gen_opl can't handle ptr + long long */
gen_cast(&int_type);
#endif
type1 = vtop[-1].type;
type1.t &= ~VT_ARRAY;
if (vtop[-1].type.t & VT_VLA)
vla_runtime_pointed_size(&vtop[-1].type);
else {
u = pointed_size(&vtop[-1].type);
if (u < 0)
tcc_error("unknown array element size");
#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
vpushll(u);
#else
/* XXX: cast to int ? (long long case) */
vpushi(u);
#endif
}
gen_op('*');
#if 0
/* #ifdef CONFIG_TCC_BCHECK
The main reason to removing this code:
#include <stdio.h>
int main ()
{
int v[10];
int i = 10;
int j = 9;
fprintf(stderr, "v+i-j = %p\n", v+i-j);
fprintf(stderr, "v+(i-j) = %p\n", v+(i-j));
}
When this code is on. then the output looks like
v+i-j = 0xfffffffe
v+(i-j) = 0xbff84000
*/
/* if evaluating constant expression, no code should be
generated, so no bound check */
if (tcc_state->do_bounds_check && !const_wanted) {
/* if bounded pointers, we generate a special code to
test bounds */
if (op == '-') {
vpushi(0);
vswap();
gen_op('-');
}
gen_bounded_ptr_add();
} else
#endif
{
gen_opic(op);
}
/* put again type if gen_opic() swaped operands */
vtop->type = type1;
}
} else if (is_float(bt1) || is_float(bt2)) {
/* compute bigger type and do implicit casts */
if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
t = VT_LDOUBLE;
} else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
t = VT_DOUBLE;
} else {
t = VT_FLOAT;
}
/* floats can only be used for a few operations */
if (op != '+' && op != '-' && op != '*' && op != '/' &&
(op < TOK_ULT || op > TOK_GT))
tcc_error("invalid operands for binary operation");
goto std_op;
} else if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL) {
t = bt1 == VT_LLONG ? VT_LLONG : VT_INT;
if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (t | VT_UNSIGNED))
t |= VT_UNSIGNED;
goto std_op;
} else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
/* cast to biggest op */
t = VT_LLONG;
/* convert to unsigned if it does not fit in a long long */
if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
(t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
t |= VT_UNSIGNED;
goto std_op;
} else {
/* integer operations */
t = VT_INT;
/* convert to unsigned if it does not fit in an integer */
if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
(t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
t |= VT_UNSIGNED;
std_op:
/* XXX: currently, some unsigned operations are explicit, so
( run in 1.018 second using v1.01-cache-2.11-cpan-13bb782fe5a )