mirror of
https://github.com/frida/tinycc
synced 2024-12-25 22:46:49 +03:00
Import more changesets from Rob Landley's fork (part 2)
This commit is contained in:
parent
54bf8c0556
commit
d778bde7f9
16
Changelog
16
Changelog
@ -1,5 +1,21 @@
|
|||||||
version 0.9.24:
|
version 0.9.24:
|
||||||
|
|
||||||
|
- Import more changesets from Rob Landley's fork (part 2):
|
||||||
|
487: Handle long long constants in gen_opic() (Rob Landley)
|
||||||
|
484: Handle parentheses within __attribute__((...)) (Rob Landley)
|
||||||
|
480: Remove a goto in decl_initializer_alloc (Rob Landley)
|
||||||
|
475: Fix dereferences in inline assembly output (Joshua Phillips)
|
||||||
|
474: Cast ptrs to ints of different sizes correctly (Joshua Phillips)
|
||||||
|
473: Fix size of structs with empty array member (Joshua Phillips)
|
||||||
|
470: No warning for && and || with mixed pointers/integers (Rob Landley)
|
||||||
|
469: Fix symbol visibility problems in the linker (Vincent Pit)
|
||||||
|
468: Allow && and || involving pointer arguments (Rob Landley)
|
||||||
|
455: Optimize case labels with no code in between (Zdenek Pavlas)
|
||||||
|
450: Implement alloca for x86 (grischka)
|
||||||
|
415: Parse unicode escape sequences (Axel Liljencrantz)
|
||||||
|
407: Add a simple va_copy() in stdarg.h (Hasso Tepper)
|
||||||
|
400: Allow typedef names as symbols (Dave Dodge)
|
||||||
|
|
||||||
- Import some changesets from Rob Landley's fork (part 1):
|
- Import some changesets from Rob Landley's fork (part 1):
|
||||||
462: Use LGPL with bcheck.c and il-gen.c
|
462: Use LGPL with bcheck.c and il-gen.c
|
||||||
458: Fix global compound literals (in unary: case '&':) (Andrew Johnson)
|
458: Fix global compound literals (in unary: case '&':) (Andrew Johnson)
|
||||||
|
13
Makefile
13
Makefile
@ -176,6 +176,9 @@ else
|
|||||||
LIBTCC1_OBJS=libtcc1.o
|
LIBTCC1_OBJS=libtcc1.o
|
||||||
LIBTCC1_CC=$(CC)
|
LIBTCC1_CC=$(CC)
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(ARCH),i386)
|
||||||
|
LIBTCC1_OBJS+=alloca86.o alloca86-bt.o
|
||||||
|
endif
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(LIBTCC1_CC) -O2 -Wall -c -o $@ $<
|
$(LIBTCC1_CC) -O2 -Wall -c -o $@ $<
|
||||||
@ -237,7 +240,11 @@ libinstall: libtcc.a
|
|||||||
$(INSTALL) -m644 libtcc.h "$(includedir)"
|
$(INSTALL) -m644 libtcc.h "$(includedir)"
|
||||||
|
|
||||||
libtcc.o: tcc.c i386-gen.c Makefile
|
libtcc.o: tcc.c i386-gen.c Makefile
|
||||||
|
ifdef CONFIG_WIN32
|
||||||
|
$(CC) $(CFLAGS) -DTCC_TARGET_PE -DLIBTCC -c -o $@ $<
|
||||||
|
else
|
||||||
$(CC) $(CFLAGS) -DLIBTCC -c -o $@ $<
|
$(CC) $(CFLAGS) -DLIBTCC -c -o $@ $<
|
||||||
|
endif
|
||||||
|
|
||||||
libtcc.a: libtcc.o
|
libtcc.a: libtcc.o
|
||||||
$(AR) rcs $@ $^
|
$(AR) rcs $@ $^
|
||||||
@ -282,11 +289,11 @@ cache: tcc_g
|
|||||||
|
|
||||||
# documentation and man page
|
# documentation and man page
|
||||||
tcc-doc.html: tcc-doc.texi
|
tcc-doc.html: tcc-doc.texi
|
||||||
texi2html -monolithic -number $<
|
-texi2html -monolithic -number $<
|
||||||
|
|
||||||
tcc.1: tcc-doc.texi
|
tcc.1: tcc-doc.texi
|
||||||
./texi2pod.pl $< tcc.pod
|
-./texi2pod.pl $< tcc.pod
|
||||||
pod2man --section=1 --center=" " --release=" " tcc.pod > $@
|
-pod2man --section=1 --center=" " --release=" " tcc.pod > $@
|
||||||
|
|
||||||
FILE=tcc-$(shell cat VERSION)
|
FILE=tcc-$(shell cat VERSION)
|
||||||
|
|
||||||
|
5
stddef.h
5
stddef.h
@ -18,4 +18,9 @@ typedef int int32_t;
|
|||||||
typedef long long int int64_t;
|
typedef long long int int64_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
|
void *_alloca(size_t);
|
||||||
|
#define alloca _alloca
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
141
tcc.c
141
tcc.c
@ -1290,6 +1290,7 @@ static void put_extern_sym2(Sym *sym, Section *section,
|
|||||||
case TOK_memset:
|
case TOK_memset:
|
||||||
case TOK_strlen:
|
case TOK_strlen:
|
||||||
case TOK_strcpy:
|
case TOK_strcpy:
|
||||||
|
case TOK__alloca:
|
||||||
strcpy(buf, "__bound_");
|
strcpy(buf, "__bound_");
|
||||||
strcat(buf, name);
|
strcat(buf, name);
|
||||||
name = buf;
|
name = buf;
|
||||||
@ -3123,6 +3124,8 @@ static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long
|
|||||||
c = n;
|
c = n;
|
||||||
goto add_char_nonext;
|
goto add_char_nonext;
|
||||||
case 'x':
|
case 'x':
|
||||||
|
case 'u':
|
||||||
|
case 'U':
|
||||||
p++;
|
p++;
|
||||||
n = 0;
|
n = 0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
@ -5329,23 +5332,29 @@ void gen_opl(int op)
|
|||||||
independent opt */
|
independent opt */
|
||||||
void gen_opic(int op)
|
void gen_opic(int op)
|
||||||
{
|
{
|
||||||
int fc, c1, c2, n;
|
int c1, c2, t1, t2, n, c;
|
||||||
SValue *v1, *v2;
|
SValue *v1, *v2;
|
||||||
|
long long l1, l2, l;
|
||||||
|
typedef unsigned long long U;
|
||||||
|
|
||||||
v1 = vtop - 1;
|
v1 = vtop - 1;
|
||||||
v2 = vtop;
|
v2 = vtop;
|
||||||
|
t1 = v1->type.t & VT_BTYPE;
|
||||||
|
t2 = v2->type.t & VT_BTYPE;
|
||||||
|
l1 = (t1 == VT_LLONG) ? v1->c.ll : v1->c.i;
|
||||||
|
l2 = (t2 == VT_LLONG) ? v2->c.ll : v2->c.i;
|
||||||
|
|
||||||
/* currently, we cannot do computations with forward symbols */
|
/* currently, we cannot do computations with forward symbols */
|
||||||
c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
|
c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
|
||||||
c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
|
c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
|
||||||
if (c1 && c2) {
|
if (c1 && c2) {
|
||||||
fc = v2->c.i;
|
|
||||||
switch(op) {
|
switch(op) {
|
||||||
case '+': v1->c.i += fc; break;
|
case '+': l1 += l2; break;
|
||||||
case '-': v1->c.i -= fc; break;
|
case '-': l1 -= l2; break;
|
||||||
case '&': v1->c.i &= fc; break;
|
case '&': l1 &= l2; break;
|
||||||
case '^': v1->c.i ^= fc; break;
|
case '^': l1 ^= l2; break;
|
||||||
case '|': v1->c.i |= fc; break;
|
case '|': l1 |= l2; break;
|
||||||
case '*': v1->c.i *= fc; break;
|
case '*': l1 *= l2; break;
|
||||||
|
|
||||||
case TOK_PDIV:
|
case TOK_PDIV:
|
||||||
case '/':
|
case '/':
|
||||||
@ -5353,66 +5362,68 @@ void gen_opic(int op)
|
|||||||
case TOK_UDIV:
|
case TOK_UDIV:
|
||||||
case TOK_UMOD:
|
case TOK_UMOD:
|
||||||
/* if division by zero, generate explicit division */
|
/* if division by zero, generate explicit division */
|
||||||
if (fc == 0) {
|
if (l2 == 0) {
|
||||||
if (const_wanted)
|
if (const_wanted)
|
||||||
error("division by zero in constant");
|
error("division by zero in constant");
|
||||||
goto general_case;
|
goto general_case;
|
||||||
}
|
}
|
||||||
switch(op) {
|
switch(op) {
|
||||||
default: v1->c.i /= fc; break;
|
default: l1 /= l2; break;
|
||||||
case '%': v1->c.i %= fc; break;
|
case '%': l1 %= l2; break;
|
||||||
case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
|
case TOK_UDIV: l1 = (U)l1 / l2; break;
|
||||||
case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
|
case TOK_UMOD: l1 = (U)l1 % l2; break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TOK_SHL: v1->c.i <<= fc; break;
|
case TOK_SHL: l1 <<= l2; break;
|
||||||
case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
|
case TOK_SHR: l1 = (U)l1 >> l2; break;
|
||||||
case TOK_SAR: v1->c.i >>= fc; break;
|
case TOK_SAR: l1 >>= l2; break;
|
||||||
/* tests */
|
/* tests */
|
||||||
case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
|
case TOK_ULT: l1 = (U)l1 < (U)l2; break;
|
||||||
case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
|
case TOK_UGE: l1 = (U)l1 >= (U)l2; break;
|
||||||
case TOK_EQ: v1->c.i = v1->c.i == fc; break;
|
case TOK_EQ: l1 = l1 == l2; break;
|
||||||
case TOK_NE: v1->c.i = v1->c.i != fc; break;
|
case TOK_NE: l1 = l1 != l2; break;
|
||||||
case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
|
case TOK_ULE: l1 = (U)l1 <= (U)l2; break;
|
||||||
case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
|
case TOK_UGT: l1 = (U)l1 > (U)l2; break;
|
||||||
case TOK_LT: v1->c.i = v1->c.i < fc; break;
|
case TOK_LT: l1 = l1 < l2; break;
|
||||||
case TOK_GE: v1->c.i = v1->c.i >= fc; break;
|
case TOK_GE: l1 = l1 >= l2; break;
|
||||||
case TOK_LE: v1->c.i = v1->c.i <= fc; break;
|
case TOK_LE: l1 = l1 <= l2; break;
|
||||||
case TOK_GT: v1->c.i = v1->c.i > fc; break;
|
case TOK_GT: l1 = l1 > l2; break;
|
||||||
/* logical */
|
/* logical */
|
||||||
case TOK_LAND: v1->c.i = v1->c.i && fc; break;
|
case TOK_LAND: l1 = l1 && l2; break;
|
||||||
case TOK_LOR: v1->c.i = v1->c.i || fc; break;
|
case TOK_LOR: l1 = l1 || l2; break;
|
||||||
default:
|
default:
|
||||||
goto general_case;
|
goto general_case;
|
||||||
}
|
}
|
||||||
|
v1->c.ll = l1;
|
||||||
vtop--;
|
vtop--;
|
||||||
} else {
|
} else {
|
||||||
/* if commutative ops, put c2 as constant */
|
/* if commutative ops, put c2 as constant */
|
||||||
if (c1 && (op == '+' || op == '&' || op == '^' ||
|
if (c1 && (op == '+' || op == '&' || op == '^' ||
|
||||||
op == '|' || op == '*')) {
|
op == '|' || op == '*')) {
|
||||||
vswap();
|
vswap();
|
||||||
swap(&c1, &c2);
|
c = c1, c1 = c2, c2 = c;
|
||||||
|
l = l1, l1 = l2, l2 = l;
|
||||||
}
|
}
|
||||||
fc = vtop->c.i;
|
/* Filter out NOP operations like x*1, x-0, x&-1... */
|
||||||
if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
|
if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
|
||||||
op == TOK_PDIV) &&
|
op == TOK_PDIV) &&
|
||||||
fc == 1) ||
|
l2 == 1) ||
|
||||||
((op == '+' || op == '-' || op == '|' || op == '^' ||
|
((op == '+' || op == '-' || op == '|' || op == '^' ||
|
||||||
op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
|
op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
|
||||||
fc == 0) ||
|
l2 == 0) ||
|
||||||
(op == '&' &&
|
(op == '&' &&
|
||||||
fc == -1))) {
|
l2 == -1))) {
|
||||||
/* nothing to do */
|
/* nothing to do */
|
||||||
vtop--;
|
vtop--;
|
||||||
} else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
|
} else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
|
||||||
/* try to use shifts instead of muls or divs */
|
/* try to use shifts instead of muls or divs */
|
||||||
if (fc > 0 && (fc & (fc - 1)) == 0) {
|
if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
|
||||||
n = -1;
|
n = -1;
|
||||||
while (fc) {
|
while (l2) {
|
||||||
fc >>= 1;
|
l2 >>= 1;
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
vtop->c.i = n;
|
vtop->c.ll = n;
|
||||||
if (op == '*')
|
if (op == '*')
|
||||||
op = TOK_SHL;
|
op = TOK_SHL;
|
||||||
else if (op == TOK_PDIV)
|
else if (op == TOK_PDIV)
|
||||||
@ -5426,13 +5437,16 @@ void gen_opic(int op)
|
|||||||
(VT_CONST | VT_SYM)) {
|
(VT_CONST | VT_SYM)) {
|
||||||
/* symbol + constant case */
|
/* symbol + constant case */
|
||||||
if (op == '-')
|
if (op == '-')
|
||||||
fc = -fc;
|
l2 = -l2;
|
||||||
vtop--;
|
vtop--;
|
||||||
vtop->c.i += fc;
|
vtop->c.ll += l2;
|
||||||
} else {
|
} else {
|
||||||
general_case:
|
general_case:
|
||||||
if (!nocode_wanted) {
|
if (!nocode_wanted) {
|
||||||
/* call low level op generator */
|
/* call low level op generator */
|
||||||
|
if (t1 == VT_LLONG || t2 == VT_LLONG)
|
||||||
|
gen_opl(op);
|
||||||
|
else
|
||||||
gen_opi(op);
|
gen_opi(op);
|
||||||
} else {
|
} else {
|
||||||
vtop--;
|
vtop--;
|
||||||
@ -5540,6 +5554,7 @@ static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
|
|||||||
bt2 = type2->t & VT_BTYPE;
|
bt2 = type2->t & VT_BTYPE;
|
||||||
/* accept comparison between pointer and integer with a warning */
|
/* accept comparison between pointer and integer with a warning */
|
||||||
if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
|
if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
|
||||||
|
if (op != TOK_LOR && op != TOK_LAND )
|
||||||
warning("comparison between pointer and integer");
|
warning("comparison between pointer and integer");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -5586,7 +5601,7 @@ void gen_op(int op)
|
|||||||
if (bt1 == VT_PTR || bt2 == VT_PTR) {
|
if (bt1 == VT_PTR || bt2 == VT_PTR) {
|
||||||
/* at least one operand is a pointer */
|
/* at least one operand is a pointer */
|
||||||
/* relationnal op: must be both pointers */
|
/* relationnal op: must be both pointers */
|
||||||
if (op >= TOK_ULT && op <= TOK_GT) {
|
if (op >= TOK_ULT && op <= TOK_LOR) {
|
||||||
check_comparison_pointer_types(vtop - 1, vtop, op);
|
check_comparison_pointer_types(vtop - 1, vtop, op);
|
||||||
/* pointers are handled are unsigned */
|
/* pointers are handled are unsigned */
|
||||||
t = VT_INT | VT_UNSIGNED;
|
t = VT_INT | VT_UNSIGNED;
|
||||||
@ -5696,8 +5711,6 @@ void gen_op(int op)
|
|||||||
gen_cast(&type1);
|
gen_cast(&type1);
|
||||||
if (is_float(t))
|
if (is_float(t))
|
||||||
gen_opif(op);
|
gen_opif(op);
|
||||||
else if ((t & VT_BTYPE) == VT_LLONG)
|
|
||||||
gen_opl(op);
|
|
||||||
else
|
else
|
||||||
gen_opic(op);
|
gen_opic(op);
|
||||||
if (op >= TOK_ULT && op <= TOK_GT) {
|
if (op >= TOK_ULT && op <= TOK_GT) {
|
||||||
@ -5947,6 +5960,11 @@ static void gen_cast(CType *type)
|
|||||||
the lvalue already contains the real type size (see
|
the lvalue already contains the real type size (see
|
||||||
VT_LVAL_xxx constants) */
|
VT_LVAL_xxx constants) */
|
||||||
}
|
}
|
||||||
|
} else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) {
|
||||||
|
/* if we are casting between pointer types,
|
||||||
|
we must update the VT_LVAL_xxx size */
|
||||||
|
vtop->r = (vtop->r & ~VT_LVAL_TYPE)
|
||||||
|
| (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE);
|
||||||
}
|
}
|
||||||
vtop->type = *type;
|
vtop->type = *type;
|
||||||
}
|
}
|
||||||
@ -6502,12 +6520,15 @@ static void parse_attribute(AttributeDef *ad)
|
|||||||
if (tcc_state->warn_unsupported)
|
if (tcc_state->warn_unsupported)
|
||||||
warning("'%s' attribute ignored", get_tok_str(t, NULL));
|
warning("'%s' attribute ignored", get_tok_str(t, NULL));
|
||||||
/* skip parameters */
|
/* skip parameters */
|
||||||
/* XXX: skip parenthesis too */
|
|
||||||
if (tok == '(') {
|
if (tok == '(') {
|
||||||
|
int parenthesis = 0;
|
||||||
|
do {
|
||||||
|
if (tok == '(')
|
||||||
|
parenthesis++;
|
||||||
|
else if (tok == ')')
|
||||||
|
parenthesis--;
|
||||||
next();
|
next();
|
||||||
while (tok != ')' && tok != -1)
|
} while (parenthesis && tok != -1);
|
||||||
next();
|
|
||||||
next();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -6668,6 +6689,7 @@ static void struct_decl(CType *type, int u)
|
|||||||
if (a == TOK_STRUCT) {
|
if (a == TOK_STRUCT) {
|
||||||
c = (c + align - 1) & -align;
|
c = (c + align - 1) & -align;
|
||||||
offset = c;
|
offset = c;
|
||||||
|
if (size > 0)
|
||||||
c += size;
|
c += size;
|
||||||
} else {
|
} else {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
@ -6719,13 +6741,14 @@ static void struct_decl(CType *type, int u)
|
|||||||
*/
|
*/
|
||||||
static int parse_btype(CType *type, AttributeDef *ad)
|
static int parse_btype(CType *type, AttributeDef *ad)
|
||||||
{
|
{
|
||||||
int t, u, type_found, typespec_found;
|
int t, u, type_found, typespec_found, typedef_found;
|
||||||
Sym *s;
|
Sym *s;
|
||||||
CType type1;
|
CType type1;
|
||||||
|
|
||||||
memset(ad, 0, sizeof(AttributeDef));
|
memset(ad, 0, sizeof(AttributeDef));
|
||||||
type_found = 0;
|
type_found = 0;
|
||||||
typespec_found = 0;
|
typespec_found = 0;
|
||||||
|
typedef_found = 0;
|
||||||
t = 0;
|
t = 0;
|
||||||
while(1) {
|
while(1) {
|
||||||
switch(tok) {
|
switch(tok) {
|
||||||
@ -6858,11 +6881,12 @@ static int parse_btype(CType *type, AttributeDef *ad)
|
|||||||
parse_expr_type(&type1);
|
parse_expr_type(&type1);
|
||||||
goto basic_type2;
|
goto basic_type2;
|
||||||
default:
|
default:
|
||||||
if (typespec_found)
|
if (typespec_found || typedef_found)
|
||||||
goto the_end;
|
goto the_end;
|
||||||
s = sym_find(tok);
|
s = sym_find(tok);
|
||||||
if (!s || !(s->type.t & VT_TYPEDEF))
|
if (!s || !(s->type.t & VT_TYPEDEF))
|
||||||
goto the_end;
|
goto the_end;
|
||||||
|
typedef_found = 1;
|
||||||
t |= (s->type.t & ~VT_TYPEDEF);
|
t |= (s->type.t & ~VT_TYPEDEF);
|
||||||
type->ref = s->type.ref;
|
type->ref = s->type.ref;
|
||||||
next();
|
next();
|
||||||
@ -8164,6 +8188,9 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
|||||||
int v1, v2;
|
int v1, v2;
|
||||||
if (!case_sym)
|
if (!case_sym)
|
||||||
expect("switch");
|
expect("switch");
|
||||||
|
/* since a case is like a label, we must skip it with a jmp */
|
||||||
|
b = gjmp(0);
|
||||||
|
next_case:
|
||||||
next();
|
next();
|
||||||
v1 = expr_const();
|
v1 = expr_const();
|
||||||
v2 = v1;
|
v2 = v1;
|
||||||
@ -8173,24 +8200,26 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
|||||||
if (v2 < v1)
|
if (v2 < v1)
|
||||||
warning("empty case range");
|
warning("empty case range");
|
||||||
}
|
}
|
||||||
/* since a case is like a label, we must skip it with a jmp */
|
|
||||||
b = gjmp(0);
|
|
||||||
gsym(*case_sym);
|
gsym(*case_sym);
|
||||||
vseti(case_reg, 0);
|
vseti(case_reg, 0);
|
||||||
vpushi(v1);
|
vpushi(v1);
|
||||||
if (v1 == v2) {
|
if (v1 == v2) {
|
||||||
gen_op(TOK_EQ);
|
gen_op(TOK_EQ);
|
||||||
*case_sym = gtst(1, 0);
|
*case_sym = 0;
|
||||||
} else {
|
} else {
|
||||||
gen_op(TOK_GE);
|
gen_op(TOK_GE);
|
||||||
*case_sym = gtst(1, 0);
|
*case_sym = gtst(1, 0);
|
||||||
vseti(case_reg, 0);
|
vseti(case_reg, 0);
|
||||||
vpushi(v2);
|
vpushi(v2);
|
||||||
gen_op(TOK_LE);
|
gen_op(TOK_LE);
|
||||||
*case_sym = gtst(1, *case_sym);
|
|
||||||
}
|
}
|
||||||
gsym(b);
|
|
||||||
skip(':');
|
skip(':');
|
||||||
|
if (tok == TOK_CASE) {
|
||||||
|
b = gtst(0, b);
|
||||||
|
goto next_case;
|
||||||
|
}
|
||||||
|
*case_sym = gtst(1, *case_sym);
|
||||||
|
gsym(b);
|
||||||
is_expr = 0;
|
is_expr = 0;
|
||||||
goto block_after_label;
|
goto block_after_label;
|
||||||
} else
|
} else
|
||||||
@ -8873,11 +8902,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (v) {
|
if (v) {
|
||||||
if (scope == VT_CONST) {
|
if (scope != VT_CONST || !sym) {
|
||||||
if (!sym)
|
|
||||||
goto do_def;
|
|
||||||
} else {
|
|
||||||
do_def:
|
|
||||||
sym = sym_push(v, type, r | VT_SYM, 0);
|
sym = sym_push(v, type, r | VT_SYM, 0);
|
||||||
}
|
}
|
||||||
/* update symbol definition */
|
/* update symbol definition */
|
||||||
|
2
tccasm.c
2
tccasm.c
@ -806,7 +806,7 @@ static void subst_asm_operands(ASMOperand *operands, int nb_operands,
|
|||||||
sv = *op->vt;
|
sv = *op->vt;
|
||||||
if (op->reg >= 0) {
|
if (op->reg >= 0) {
|
||||||
sv.r = op->reg;
|
sv.r = op->reg;
|
||||||
if ((op->vt->r & VT_VALMASK) == VT_LLOCAL)
|
if ((op->vt->r & VT_VALMASK) == VT_LLOCAL && op->is_memory)
|
||||||
sv.r |= VT_LVAL;
|
sv.r |= VT_LVAL;
|
||||||
}
|
}
|
||||||
subst_asm_operand(out_str, &sv, modifier);
|
subst_asm_operand(out_str, &sv, modifier);
|
||||||
|
17
tccelf.c
17
tccelf.c
@ -182,9 +182,11 @@ static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
|
|||||||
{
|
{
|
||||||
Elf32_Sym *esym;
|
Elf32_Sym *esym;
|
||||||
int sym_bind, sym_index, sym_type, esym_bind;
|
int sym_bind, sym_index, sym_type, esym_bind;
|
||||||
|
unsigned char sym_vis, esym_vis, new_vis;
|
||||||
|
|
||||||
sym_bind = ELF32_ST_BIND(info);
|
sym_bind = ELF32_ST_BIND(info);
|
||||||
sym_type = ELF32_ST_TYPE(info);
|
sym_type = ELF32_ST_TYPE(info);
|
||||||
|
sym_vis = ELF32_ST_VISIBILITY(other);
|
||||||
|
|
||||||
if (sym_bind != STB_LOCAL) {
|
if (sym_bind != STB_LOCAL) {
|
||||||
/* we search global or weak symbols */
|
/* we search global or weak symbols */
|
||||||
@ -194,6 +196,19 @@ static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
|
|||||||
esym = &((Elf32_Sym *)s->data)[sym_index];
|
esym = &((Elf32_Sym *)s->data)[sym_index];
|
||||||
if (esym->st_shndx != SHN_UNDEF) {
|
if (esym->st_shndx != SHN_UNDEF) {
|
||||||
esym_bind = ELF32_ST_BIND(esym->st_info);
|
esym_bind = ELF32_ST_BIND(esym->st_info);
|
||||||
|
/* propagate the most constraining visibility */
|
||||||
|
/* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
|
||||||
|
esym_vis = ELF32_ST_VISIBILITY(esym->st_other);
|
||||||
|
if (esym_vis == STV_DEFAULT) {
|
||||||
|
new_vis = sym_vis;
|
||||||
|
} else if (sym_vis == STV_DEFAULT) {
|
||||||
|
new_vis = esym_vis;
|
||||||
|
} else {
|
||||||
|
new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
|
||||||
|
}
|
||||||
|
esym->st_other = (esym->st_other & ~ELF32_ST_VISIBILITY(-1))
|
||||||
|
| new_vis;
|
||||||
|
other = esym->st_other; /* in case we have to patch esym */
|
||||||
if (sh_num == SHN_UNDEF) {
|
if (sh_num == SHN_UNDEF) {
|
||||||
/* ignore adding of undefined symbol if the
|
/* ignore adding of undefined symbol if the
|
||||||
corresponding symbol is already defined */
|
corresponding symbol is already defined */
|
||||||
@ -202,6 +217,8 @@ static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
|
|||||||
goto do_patch;
|
goto do_patch;
|
||||||
} else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
|
} else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
|
||||||
/* weak is ignored if already global */
|
/* weak is ignored if already global */
|
||||||
|
} else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
|
||||||
|
/* ignore hidden symbols after */
|
||||||
} else {
|
} else {
|
||||||
#if 0
|
#if 0
|
||||||
printf("new_bind=%d new_shndx=%d last_bind=%d old_shndx=%d\n",
|
printf("new_bind=%d new_shndx=%d last_bind=%d old_shndx=%d\n",
|
||||||
|
2
tcctok.h
2
tcctok.h
@ -123,7 +123,6 @@
|
|||||||
/* builtin functions or variables */
|
/* builtin functions or variables */
|
||||||
DEF(TOK_memcpy, "memcpy")
|
DEF(TOK_memcpy, "memcpy")
|
||||||
DEF(TOK_memset, "memset")
|
DEF(TOK_memset, "memset")
|
||||||
DEF(TOK_alloca, "alloca")
|
|
||||||
DEF(TOK___divdi3, "__divdi3")
|
DEF(TOK___divdi3, "__divdi3")
|
||||||
DEF(TOK___moddi3, "__moddi3")
|
DEF(TOK___moddi3, "__moddi3")
|
||||||
DEF(TOK___udivdi3, "__udivdi3")
|
DEF(TOK___udivdi3, "__udivdi3")
|
||||||
@ -188,6 +187,7 @@
|
|||||||
DEF(TOK_memmove, "memmove")
|
DEF(TOK_memmove, "memmove")
|
||||||
DEF(TOK_strlen, "strlen")
|
DEF(TOK_strlen, "strlen")
|
||||||
DEF(TOK_strcpy, "strcpy")
|
DEF(TOK_strcpy, "strcpy")
|
||||||
|
DEF(TOK__alloca, "_alloca")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Tiny Assembler */
|
/* Tiny Assembler */
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
#ifndef __MINGW_H
|
#ifndef __MINGW_H
|
||||||
#define __MINGW_H
|
#define __MINGW_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#define __int64 long long
|
#define __int64 long long
|
||||||
#define __int32 long
|
#define __int32 long
|
||||||
#define __int16 short
|
#define __int16 short
|
||||||
|
@ -6,6 +6,7 @@ typedef char *va_list;
|
|||||||
/* only correct for i386 */
|
/* only correct for i386 */
|
||||||
#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3)
|
#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3)
|
||||||
#define va_arg(ap,type) (ap += (sizeof(type)+3)&~3, *(type *)(ap - ((sizeof(type)+3)&~3)))
|
#define va_arg(ap,type) (ap += (sizeof(type)+3)&~3, *(type *)(ap - ((sizeof(type)+3)&~3)))
|
||||||
|
#define va_copy(dest, src) (dest) = (src)
|
||||||
#define va_end(ap)
|
#define va_end(ap)
|
||||||
|
|
||||||
/* fix a buggy dependency on GCC in libio.h */
|
/* fix a buggy dependency on GCC in libio.h */
|
||||||
|
@ -18,4 +18,9 @@ typedef int int32_t;
|
|||||||
typedef long long int int64_t;
|
typedef long long int int64_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
|
void *_alloca(size_t);
|
||||||
|
#define alloca _alloca
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user