some reverts & fixes
Some checks failed
build and test / test-x86_64-linux (push) Has been cancelled
build and test / test-x86_64-osx (push) Has been cancelled
build and test / test-aarch64-osx (push) Has been cancelled
build and test / test-x86_64-win32 (push) Has been cancelled
build and test / test-i386-win32 (push) Has been cancelled
build and test / test-armv7-linux (push) Has been cancelled
build and test / test-aarch64-linux (push) Has been cancelled
build and test / test-riscv64-linux (push) Has been cancelled

workflow:
- revert 'pinact for security' for readability
  from 831c3fa184
tccpp.c:
- remove code that allows tcc to parse numbers incorrectly (*)
  from 829c848520
tccgen.c:
- Revert "Relaxed the 'incompatible pointer type' warning a bit" (*)
  from d9ec17d334.
tccrun.c:
- remove support for -nostdlib -run
  for simplicity, we require "main" with tcc -run always
tccpp.c:
- Revert "Free all preprocessor memmory in case of error."
  from c96f0cad61
  Remove TinyAlloc->limit instead.  Thus it can do also bigger
  allocs.  Big TokenStrings (like 200kb+ when compiling tcc)
  may come from inline functions or from large initializers.
Makefile/configure:
- use --config-pie for configuring tcc output only
- use -fPIC with clang-x86_64 to avoid 32-bit relocs
libtcc.c:
- fix "tcc file.c -run" i.e. -run as last argument
i386-gen.c:
- PIC refactor

(*) sorry, but code in tcc should have a minimum of generic relevance
This commit is contained in:
grischka 2025-12-21 10:19:01 +01:00
parent 518279dc3e
commit 5ec0e6f84b
24 changed files with 300 additions and 742 deletions

View File

@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
timeout-minutes: 2 timeout-minutes: 2
steps: steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/checkout@v4
- name: make & test tcc (x86_64-linux) - name: make & test tcc (x86_64-linux)
run: ./configure && make && make test -k run: ./configure && make && make test -k
@ -17,7 +17,7 @@ jobs:
runs-on: macos-15-intel runs-on: macos-15-intel
timeout-minutes: 2 timeout-minutes: 2
steps: steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/checkout@v4
- name: make & test tcc (x86_64-osx) - name: make & test tcc (x86_64-osx)
run: ./configure && make && make test -k run: ./configure && make && make test -k
@ -25,7 +25,7 @@ jobs:
runs-on: macos-15 runs-on: macos-15
timeout-minutes: 2 timeout-minutes: 2
steps: steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/checkout@v4
- name: make & test tcc (aarch64-osx) - name: make & test tcc (aarch64-osx)
run: ./configure && make && make test -k run: ./configure && make && make test -k
@ -33,7 +33,7 @@ jobs:
runs-on: windows-2025 runs-on: windows-2025
timeout-minutes: 6 timeout-minutes: 6
steps: steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/checkout@v4
- name: make & test tcc (x86_64-win32) - name: make & test tcc (x86_64-win32)
shell: cmd shell: cmd
run: | run: |
@ -44,7 +44,7 @@ jobs:
C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-x86_64-gcc" C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-x86_64-gcc"
echo ::endgroup:: echo ::endgroup::
C:\msys64\usr\bin\bash -l -c "./configure && make && make test -k" C:\msys64\usr\bin\bash -l -c "./configure && make && make test -k"
- uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 - uses: ilammy/msvc-dev-cmd@v1
with: with:
arch: amd64 arch: amd64
- name: build with MSVC (x86_64-win32) - name: build with MSVC (x86_64-win32)
@ -61,7 +61,7 @@ jobs:
runs-on: windows-2025 runs-on: windows-2025
timeout-minutes: 6 timeout-minutes: 6
steps: steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/checkout@v4
- name: make & test tcc (i386-win32) - name: make & test tcc (i386-win32)
shell: cmd shell: cmd
run: | run: |
@ -72,7 +72,7 @@ jobs:
C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-i686-gcc" C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-i686-gcc"
echo ::endgroup:: echo ::endgroup::
C:\msys64\usr\bin\bash -l -c "./configure && make && make test -k" C:\msys64\usr\bin\bash -l -c "./configure && make && make test -k"
- uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 - uses: ilammy/msvc-dev-cmd@v1
with: with:
arch: x86 arch: x86
- name: build with MSVC (i386-win32) - name: build with MSVC (i386-win32)
@ -89,8 +89,8 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
timeout-minutes: 8 timeout-minutes: 8
steps: steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/checkout@v4
- uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1 - uses: uraimo/run-on-arch-action@v3
name: make & test tcc (armv7-linux) name: make & test tcc (armv7-linux)
with: with:
arch: armv7 arch: armv7
@ -107,8 +107,8 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
timeout-minutes: 8 timeout-minutes: 8
steps: steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/checkout@v4
- uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1 - uses: uraimo/run-on-arch-action@v3
name: make & test tcc (aarch64-linux) name: make & test tcc (aarch64-linux)
with: with:
arch: aarch64 arch: aarch64
@ -125,8 +125,8 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
timeout-minutes: 8 timeout-minutes: 8
steps: steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - uses: actions/checkout@v4
- uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1 - uses: uraimo/run-on-arch-action@v3
name: make & test tcc (riscv64-linux) name: make & test tcc (riscv64-linux)
with: with:
arch: riscv64 arch: riscv64

View File

@ -24,11 +24,6 @@ CFLAGS += $(CPPFLAGS)
VPATH = $(TOPSRC) VPATH = $(TOPSRC)
-LTCC = $(TOP)/$(LIBTCC) -LTCC = $(TOP)/$(LIBTCC)
ifeq ($(CONFIG_pie),yes)
CFLAGS += -fPIE
LDFLAGS += -pie
endif
ifdef CONFIG_WIN32 ifdef CONFIG_WIN32
CFG = -win CFG = -win
ifneq ($(CONFIG_static),yes) ifneq ($(CONFIG_static),yes)
@ -296,6 +291,11 @@ tcc_p$(EXESUF): $($T_FILES)
libtcc.a: $(LIBTCC_OBJ) libtcc.a: $(LIBTCC_OBJ)
$S$(AR) rcs $@ $^ $S$(AR) rcs $@ $^
ifeq ($(CC_NAME)-$(ARCH),clang-x86_64)
# avoid 32-bit relocations in libtcc.a for its usage with tcc -run
libtcc.a: override CFLAGS += -fPIC
endif
# dynamic libtcc library # dynamic libtcc library
libtcc.so: $(LIBTCC_OBJ) libtcc.so: $(LIBTCC_OBJ)
$S$(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LIBS) $(LDFLAGS) $S$(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LIBS) $(LDFLAGS)
@ -372,7 +372,7 @@ IR = $(IM) mkdir -p $2 && cp -r $1/. $2
IM = @echo "-> $2 : $1" ; IM = @echo "-> $2 : $1" ;
BINCHECK = $(if $(wildcard $(PROGS) *-tcc$(EXESUF)),,@echo "Makefile: nothing found to install" && exit 1) BINCHECK = $(if $(wildcard $(PROGS) *-tcc$(EXESUF)),,@echo "Makefile: nothing found to install" && exit 1)
EXTRA_O = runmain.o run_nostdlib.o bt-exe.o bt-dll.o bt-log.o bcheck.o get_pc_thunk.o EXTRA_O = runmain.o bt-exe.o bt-dll.o bt-log.o bcheck.o
# install progs & libs # install progs & libs
install-unx: install-unx:
@ -394,7 +394,7 @@ endif
# uninstall # uninstall
uninstall-unx: uninstall-unx:
@rm -fv $(addprefix "$(bindir)/",$(PROGS) $(PROGS_CROSS)) @rm -fv $(addprefix "$(bindir)/",$(PROGS) $(PROGS_CROSS))
@rm -fv $(addprefix "$(libdir)/", libtcc*.a libtcc*.so libtcc.dylib,$P) @rm -fv $(addprefix "$(libdir)/", libtcc*.a libtcc*.so libtcc.dylib)
@rm -fv $(addprefix "$(includedir)/", libtcc.h) @rm -fv $(addprefix "$(includedir)/", libtcc.h)
@rm -fv "$(mandir)/man1/tcc.1" "$(infodir)/tcc-doc.info" @rm -fv "$(mandir)/man1/tcc.1" "$(infodir)/tcc-doc.info"
@rm -fv "$(docdir)/tcc-doc.html" @rm -fv "$(docdir)/tcc-doc.html"

View File

@ -149,11 +149,8 @@ ST_FUNC void g(int c)
if (nocode_wanted) if (nocode_wanted)
return; return;
ind1 = ind + 1; ind1 = ind + 1;
if ((unsigned)ind1 > cur_text_section->data_allocated) { if (ind1 > cur_text_section->data_allocated)
if (ind1 < 0)
tcc_error("program too big");
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
}
cur_text_section->data[ind] = c; cur_text_section->data[ind] = c;
ind = ind1; ind = ind1;
} }

View File

@ -257,11 +257,8 @@ void o(uint32_t i)
if (!cur_text_section) if (!cur_text_section)
tcc_error("compiler error! This happens f.ex. if the compiler\n" tcc_error("compiler error! This happens f.ex. if the compiler\n"
"can't evaluate constant expressions outside of a function."); "can't evaluate constant expressions outside of a function.");
if ((unsigned)ind1 > cur_text_section->data_allocated) { if (ind1 > cur_text_section->data_allocated)
if (ind1 < 0)
tcc_error("program too big");
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
}
cur_text_section->data[ind++] = i&255; cur_text_section->data[ind++] = i&255;
i>>=8; i>>=8;
cur_text_section->data[ind++] = i&255; cur_text_section->data[ind++] = i&255;

View File

@ -31,11 +31,8 @@ ST_FUNC void g(int c)
if (nocode_wanted) if (nocode_wanted)
return; return;
ind1 = ind + 1; ind1 = ind + 1;
if ((unsigned)ind1 > cur_text_section->data_allocated) { if (ind1 > cur_text_section->data_allocated)
if (ind1 < 0)
tcc_error("program too big");
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
}
cur_text_section->data[ind] = c; cur_text_section->data[ind] = c;
ind = ind1; ind = ind1;
} }

View File

@ -117,11 +117,8 @@ ST_FUNC void o(unsigned int c)
int ind1 = ind + 4; int ind1 = ind + 4;
if (nocode_wanted) if (nocode_wanted)
return; return;
if ((unsigned)ind1 > cur_text_section->data_allocated) { if (ind1 > cur_text_section->data_allocated)
if (ind1 < 0)
tcc_error("program too big");
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
}
write32le(cur_text_section->data + ind, c); write32le(cur_text_section->data + ind, c);
ind = ind1; ind = ind1;
} }

View File

@ -195,11 +195,8 @@ void C67_g(int c)
fprintf(f, " %08X", c); fprintf(f, " %08X", c);
#endif #endif
ind1 = ind + 4; ind1 = ind + 4;
if ((unsigned)ind1 > (int) cur_text_section->data_allocated) { if (ind1 > (int) cur_text_section->data_allocated)
if (ind1 < 0)
tcc_error("program too big");
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
}
cur_text_section->data[ind] = c & 0xff; cur_text_section->data[ind] = c & 0xff;
cur_text_section->data[ind + 1] = (c >> 8) & 0xff; cur_text_section->data[ind + 1] = (c >> 8) & 0xff;
cur_text_section->data[ind + 2] = (c >> 16) & 0xff; cur_text_section->data[ind + 2] = (c >> 16) & 0xff;

2
configure vendored
View File

@ -230,7 +230,7 @@ Advanced options (experts only):
--config-new_dtags=yes use new ELF DTAGs (DT_RUNPATH instead of DT_RPATH) --config-new_dtags=yes use new ELF DTAGs (DT_RUNPATH instead of DT_RPATH)
--config-codesign=no do not use codesign on apple to sign executables --config-codesign=no do not use codesign on apple to sign executables
--config-dwarf=x use dwarf debug info instead of stabs (x=2..5) --config-dwarf=x use dwarf debug info instead of stabs (x=2..5)
--config-pie compile with pie --config-pie let tcc generate position independent executables
Cross build options (experimental): Cross build options (experimental):
--cpu=CPU target CPU [$cpu] --cpu=CPU target CPU [$cpu]

View File

@ -48,7 +48,6 @@ enum {
TREG_EBX, TREG_EBX,
TREG_ST0, TREG_ST0,
TREG_ESP = 4, TREG_ESP = 4,
TREG_MEM = 0x20 TREG_MEM = 0x20
}; };
@ -90,22 +89,17 @@ ST_DATA const char * const target_machine_defs =
"__i386\0" "__i386\0"
; ;
/* define to 1/0 to [not] have EBX as 4th register */
#define USE_EBX 0
#if defined CONFIG_TCC_PIC #if defined CONFIG_TCC_PIC
#if USE_EBX > 0 # define USE_EBX 2
#error only USE_EBX or GOT_EBX can be set
#endif
#define GOT_EBX 1
#else #else
#define GOT_EBX 0 # define USE_EBX 0 /* define to 1 to have EBX as 4th register */
#endif #endif
ST_DATA const int reg_classes[NB_REGS] = { ST_DATA const int reg_classes[NB_REGS] = {
/* eax */ RC_INT | RC_EAX, /* eax */ RC_INT | RC_EAX,
/* ecx */ RC_INT | RC_ECX, /* ecx */ RC_INT | RC_ECX,
/* edx */ RC_INT | RC_EDX, /* edx */ RC_INT | RC_EDX,
/* ebx */ (RC_INT | RC_EBX) * USE_EBX, /* ebx */ (RC_INT | RC_EBX) * (USE_EBX == 1),
/* st0 */ RC_FLOAT | RC_ST0, /* st0 */ RC_FLOAT | RC_ST0,
}; };
@ -126,11 +120,8 @@ ST_FUNC void g(int c)
if (nocode_wanted) if (nocode_wanted)
return; return;
ind1 = ind + 1; ind1 = ind + 1;
if ((unsigned)ind1 > cur_text_section->data_allocated) { if (ind1 > cur_text_section->data_allocated)
if (ind1 < 0)
tcc_error("program too big");
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
}
cur_text_section->data[ind] = c; cur_text_section->data[ind] = c;
ind = ind1; ind = ind1;
} }
@ -187,33 +178,23 @@ ST_FUNC void gen_fill_nops(int bytes)
} }
#if defined CONFIG_TCC_PIC #if defined CONFIG_TCC_PIC
static void gen_static_call(int v);
static void get_pc_thunk(int r, int add) static void get_pc_thunk(int r, int add)
{ {
static const char *pc_thunk_name[] = { static const char * const pc_thunk_name[] = {
"__x86.get_pc_thunk.ax", "__x86.get_pc_thunk.ax",
"__x86.get_pc_thunk.cx", "__x86.get_pc_thunk.cx",
"__x86.get_pc_thunk.dx", "__x86.get_pc_thunk.dx",
"__x86.get_pc_thunk.bx" "__x86.get_pc_thunk.bx"
}; };
int pc_thunk;
if (nocode_wanted) if (nocode_wanted)
return; return;
gen_static_call(tok_alloc_const(pc_thunk_name[r]));
r = REG_VALUE(r);
pc_thunk = set_elf_sym(tcc_state->symtab, 0, 0,
ELFW(ST_INFO)(STB_GLOBAL, STT_FUNC),
ELFW(ST_VISIBILITY)(STV_HIDDEN),
SHN_UNDEF, pc_thunk_name[r]);
oad(0xe8, -4); /* call __x86.get_pc_thunk.rx */
put_elf_reloc(symtab_section, cur_text_section, ind - 4,
R_386_PC32, pc_thunk);
if (add) { if (add) {
Sym label = {0}; Sym label = {0};
label.type.t = VT_VOID|VT_STATIC;
label.type.t = VT_VOID | VT_STATIC;
put_extern_sym(&label, cur_text_section, ind, 0); put_extern_sym(&label, cur_text_section, ind, 0);
r = REG_VALUE(r);
if (r == 0) if (r == 0)
oad(0x05, 1); /* add _GLOBAL_OFFSET_TABLE_, %eax */ oad(0x05, 1); /* add _GLOBAL_OFFSET_TABLE_, %eax */
else else
@ -256,38 +237,37 @@ ST_FUNC void gen_addrpc32(int r, Sym *sym, int c)
/* generate a modrm reference. 'op_reg' contains the additional 3 /* generate a modrm reference. 'op_reg' contains the additional 3
opcode bits */ opcode bits */
static void gen_modrm(int opc, int op_reg, int r, Sym *sym, int c) static void gen_modrm(int opc, int op_r2, int r, Sym *sym, int c)
{ {
#if defined CONFIG_TCC_PIC int op_reg = REG_VALUE(op_r2) << 3;
int is_got = (op_reg & TREG_MEM) && !(sym->type.t & VT_STATIC);
#endif
op_reg = REG_VALUE(op_reg) << 3; #if defined CONFIG_TCC_PIC
if ((r & (VT_VALMASK|VT_SYM)) == (VT_CONST|VT_SYM)) {
int is_got = (op_r2 & TREG_MEM) && !(sym->type.t & VT_STATIC);
int here = ind;
get_pc_thunk(TREG_EBX, is_got);
o(opc);
o(0x83 | op_reg);
if (is_got) {
gen_gotpcrel(r, sym, c);
} else {
gen_addrpc32(r, sym, c + (ind - here - 1));
}
} else if ((r & VT_VALMASK) < VT_CONST && (r & TREG_MEM)) {
o(opc);
if (c) {
g(0x80 | op_reg | REG_VALUE(r));
gen_le32(c);
} else {
g(0x00 | op_reg | REG_VALUE(r));
}
} else
#endif
if ((r & VT_VALMASK) == VT_CONST) { if ((r & VT_VALMASK) == VT_CONST) {
/* constant memory reference */ /* constant memory reference */
#if defined CONFIG_TCC_PIC o(opc);
if (r & VT_SYM) { o(0x05 | op_reg);
get_pc_thunk(TREG_EBX, is_got); gen_addr32(r, sym, c);
o(opc);
o(0x83 | op_reg);
if (is_got)
gen_gotpcrel(r, sym, c);
else {
int off = 6;
off += opc & 0xff00 ? 1 : 0;
off += opc & 0xff0000 ? 1 : 0;
off += opc & 0xff000000 ? 1 : 0;
gen_addrpc32(r, sym, c + off);
}
}
else
#endif
{
o(opc);
o(0x05 | op_reg);
gen_addr32(r, sym, c);
}
} else if ((r & VT_VALMASK) == VT_LOCAL) { } else if ((r & VT_VALMASK) == VT_LOCAL) {
o(opc); o(opc);
/* currently, we use only ebp as base */ /* currently, we use only ebp as base */
@ -298,14 +278,6 @@ static void gen_modrm(int opc, int op_reg, int r, Sym *sym, int c)
} else { } else {
oad(0x85 | op_reg, c); oad(0x85 | op_reg, c);
} }
} else if ((r & VT_VALMASK) >= TREG_MEM) {
o(opc);
if (c) {
g(0x80 | op_reg | REG_VALUE(r));
gen_le32(c);
} else {
g(0x00 | op_reg | REG_VALUE(r));
}
} else { } else {
o(opc); o(opc);
g(0x00 | op_reg | (r & VT_VALMASK)); g(0x00 | op_reg | (r & VT_VALMASK));
@ -321,14 +293,13 @@ ST_FUNC void load(int r, SValue *sv)
fr = sv->r; fr = sv->r;
ft = sv->type.t & ~VT_DEFSIGN; ft = sv->type.t & ~VT_DEFSIGN;
fc = sv->c.i; fc = sv->c.i;
ft &= ~(VT_VOLATILE | VT_CONSTANT); ft &= ~(VT_VOLATILE | VT_CONSTANT);
v = fr & VT_VALMASK;
#ifndef TCC_TARGET_PE
#if defined CONFIG_TCC_PIC #if defined CONFIG_TCC_PIC
/* we use indirect access via got */ /* we use indirect access via got */
if ((fr & VT_VALMASK) == VT_CONST && (fr & VT_SYM) && if ((fr & (VT_VALMASK|VT_SYM|VT_LVAL)) == (VT_CONST|VT_SYM|VT_LVAL)
(fr & VT_LVAL) && !(sv->sym->type.t & VT_STATIC)) { && !(sv->sym->type.t & VT_STATIC)) {
/* use the result register as a temporal register */ /* use the result register as a temporal register */
int tr = r | TREG_MEM; int tr = r | TREG_MEM;
if (is_float(ft)) { if (is_float(ft)) {
@ -336,14 +307,11 @@ ST_FUNC void load(int r, SValue *sv)
tr = get_reg(RC_INT) | TREG_MEM; tr = get_reg(RC_INT) | TREG_MEM;
} }
gen_modrm(0x8b, tr, fr, sv->sym, 0); gen_modrm(0x8b, tr, fr, sv->sym, 0);
/* load from the temporal register */ /* load from the temporal register */
fr = tr | VT_LVAL; fr = tr | VT_LVAL;
} }
#endif
#endif #endif
v = fr & VT_VALMASK;
if (fr & VT_LVAL) { if (fr & VT_LVAL) {
if (v == VT_LLOCAL) { if (v == VT_LLOCAL) {
v1.type.t = VT_INT; v1.type.t = VT_INT;
@ -378,26 +346,23 @@ ST_FUNC void load(int r, SValue *sv)
} }
gen_modrm(opc, r, fr, sv->sym, fc); gen_modrm(opc, r, fr, sv->sym, fc);
} else { } else {
if (v == VT_CONST) {
#if defined CONFIG_TCC_PIC #if defined CONFIG_TCC_PIC
if (fr & VT_SYM) { if ((fr & (VT_VALMASK|VT_SYM)) == (VT_CONST|VT_SYM)) {
if (sv->sym->type.t & VT_STATIC) { if (sv->sym->type.t & VT_STATIC) {
get_pc_thunk(r, 0); get_pc_thunk(r, 0);
o(0x808d | REG_VALUE(r) * 0x900); /* lea $xx(r), r */ o(0x808d | REG_VALUE(r) * 0x900); /* lea $xx(r), r */
gen_addrpc32(fr, sv->sym, fc + 6); gen_addrpc32(fr, sv->sym, fc + 6);
} } else {
else { get_pc_thunk(r, 1);
get_pc_thunk(r, 1); o(0x808b | REG_VALUE(r) * 0x900); /* mov $xx(r), r */
o(0x808b | REG_VALUE(r) * 0x900); /* mov $xx(r), r */ gen_gotpcrel(r, sv->sym, fc);
gen_gotpcrel(r, sv->sym, fc); }
} } else
}
else
#endif #endif
{ if (v == VT_CONST) {
o(0xb8 + r); /* mov $xx, r */ o(0xb8 + r); /* mov $xx, r */
gen_addr32(fr, sv->sym, fc); gen_addr32(fr, sv->sym, fc);
}
} else if (v == VT_LOCAL) { } else if (v == VT_LOCAL) {
if (fc) { if (fc) {
/* lea xxx(%ebp), r */ /* lea xxx(%ebp), r */
@ -427,27 +392,9 @@ ST_FUNC void load(int r, SValue *sv)
/* store register 'r' in lvalue 'v' */ /* store register 'r' in lvalue 'v' */
ST_FUNC void store(int r, SValue *v) ST_FUNC void store(int r, SValue *v)
{ {
int fr, bt, ft, fc, opc, pic = 0; int fr, bt, fc, opc;
ft = v->type.t; bt = v->type.t & VT_BTYPE;
fc = v->c.i;
fr = v->r & VT_VALMASK;
ft &= ~(VT_VOLATILE | VT_CONSTANT);
bt = ft & VT_BTYPE;
#ifndef TCC_TARGET_PE
#if defined CONFIG_TCC_PIC
/* we need to access the variable via got */
if (fr == VT_CONST
&& (v->r & VT_SYM)
&& !(v->sym->type.t & VT_STATIC)) {
get_pc_thunk(TREG_EBX, 1);
o(0x9b8b); /* mov xx(%ebx),%ebx */
gen_gotpcrel(TREG_EBX, v->sym, v->c.i);
pic = 1;
}
#endif
#endif
/* XXX: incorrect if float reg to reg */ /* XXX: incorrect if float reg to reg */
if (bt == VT_FLOAT) { if (bt == VT_FLOAT) {
@ -459,26 +406,35 @@ ST_FUNC void store(int r, SValue *v)
} else if (bt == VT_LDOUBLE) { } else if (bt == VT_LDOUBLE) {
opc = 0xdbc0d9; /* fld %st(0), fstpt */ opc = 0xdbc0d9; /* fld %st(0), fstpt */
r = 7; r = 7;
} else if (bt == VT_SHORT) } else if (bt == VT_SHORT) {
opc = 0x8966; opc = 0x8966;
else if (bt == VT_BYTE || bt == VT_BOOL) } else if (bt == VT_BYTE || bt == VT_BOOL) {
opc = 0x88; opc = 0x88;
else } else {
opc = 0x89; opc = 0x89;
if (pic) { }
fc = v->c.i;
fr = v->r & VT_VALMASK;
#if defined CONFIG_TCC_PIC
/* we need to access the variable via got */
if ((v->r & (VT_VALMASK|VT_SYM)) == (VT_CONST|VT_SYM)
&& !(v->sym->type.t & VT_STATIC)) {
get_pc_thunk(TREG_EBX, 1);
o(0x9b8b); /* mov xx(%ebx),%ebx */
gen_gotpcrel(TREG_EBX, v->sym, v->c.i);
o(opc); o(opc);
o(3 + (r << 3)); o(3 + (r << 3));
} } else
else if (fr == VT_CONST || #endif
fr == VT_LOCAL ||
(v->r & VT_LVAL)) { if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) {
gen_modrm(opc, r, v->r, v->sym, fc); gen_modrm(opc, r, v->r, v->sym, fc);
} else if (fr != r) { } else if (fr != r) {
o(opc); o(opc);
o(0xc0 + fr + r * 8); /* mov r, fr */ o(0xc0 + fr + r * 8); /* mov r, fr */
} }
else
tcc_error("store problem");
} }
static void gadd_sp(int val) static void gadd_sp(int val)
@ -491,20 +447,14 @@ static void gadd_sp(int val)
} }
} }
#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_PE #if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_PE || defined CONFIG_TCC_PIC
static void gen_static_call(int v) static void gen_static_call(int v)
{ {
Sym *sym; Sym *sym;
sym = external_helper_sym(v); sym = external_helper_sym(v);
#if defined CONFIG_TCC_PIC
get_pc_thunk(TREG_EBX, 1);
oad(0xe8, -4);
greloc(cur_text_section, sym, ind - 4, R_386_PLT32);
#else
oad(0xe8, -4); oad(0xe8, -4);
greloc(cur_text_section, sym, ind - 4, R_386_PC32); greloc(cur_text_section, sym, ind - 4, R_386_PC32);
#endif
} }
#endif #endif
@ -512,22 +462,18 @@ static void gen_static_call(int v)
static void gcall_or_jmp(int is_jmp) static void gcall_or_jmp(int is_jmp)
{ {
int r; int r;
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) { if ((vtop->r & (VT_VALMASK|VT_LVAL|VT_SYM)) == (VT_CONST|VT_SYM)) {
/* constant and relocation case */ /* constant and relocation case */
#if defined CONFIG_TCC_PIC #if defined CONFIG_TCC_PIC
if (vtop->sym->type.t & VT_STATIC) { if (!(vtop->sym->type.t & VT_STATIC)) {
oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */
greloc(cur_text_section, vtop->sym, ind - 4, R_386_PC32);
}
else {
get_pc_thunk(TREG_EBX, 1); get_pc_thunk(TREG_EBX, 1);
oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */ oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */
greloc(cur_text_section, vtop->sym, ind - 4, R_386_PLT32); greloc(cur_text_section, vtop->sym, ind - 4, R_386_PLT32);
return;
} }
#else
greloc(cur_text_section, vtop->sym, ind + 1, R_386_PC32);
oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */
#endif #endif
oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */
greloc(cur_text_section, vtop->sym, ind - 4, R_386_PC32);
} else { } else {
/* otherwise, indirect call */ /* otherwise, indirect call */
r = gv(RC_INT); r = gv(RC_INT);
@ -679,9 +625,9 @@ ST_FUNC void gfunc_call(int nb_args)
} }
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
#define FUNC_PROLOG_SIZE (10 + USE_EBX) #define FUNC_PROLOG_SIZE (10 + !!USE_EBX)
#else #else
#define FUNC_PROLOG_SIZE (9 + (USE_EBX || GOT_EBX)) #define FUNC_PROLOG_SIZE (9 + !!USE_EBX)
#endif #endif
/* generate function prolog of type 't' */ /* generate function prolog of type 't' */
@ -786,7 +732,6 @@ ST_FUNC void gfunc_epilog(void)
#if USE_EBX #if USE_EBX
gen_modrm(0x8b, TREG_EBX, VT_LOCAL, NULL, -(v+4)); gen_modrm(0x8b, TREG_EBX, VT_LOCAL, NULL, -(v+4));
#endif #endif
o(0x5b * GOT_EBX); /* pop ebx */
o(0xc9); /* leave */ o(0xc9); /* leave */
if (func_ret_sub == 0) { if (func_ret_sub == 0) {
@ -812,7 +757,9 @@ ST_FUNC void gfunc_epilog(void)
o(0x90); /* adjust to FUNC_PROLOG_SIZE */ o(0x90); /* adjust to FUNC_PROLOG_SIZE */
#endif #endif
} }
o(0x53 * (USE_EBX || GOT_EBX)); /* push ebx */ #if USE_EBX
o(0x53); /* push ebx */
#endif
ind = saved_ind; ind = saved_ind;
} }

View File

@ -35,7 +35,7 @@ endif
XFLAGS += -I$(TOP) XFLAGS += -I$(TOP)
I386_O = libtcc1.o get_pc_thunk.o $(COMMON_O) I386_O = libtcc1.o $(COMMON_O)
X86_64_O = libtcc1.o $(COMMON_O) X86_64_O = libtcc1.o $(COMMON_O)
ARM_O = libtcc1.o armeabi.o armflush.o $(COMMON_O) ARM_O = libtcc1.o armeabi.o armflush.o $(COMMON_O)
ARM64_O = lib-arm64.o $(COMMON_O) ARM64_O = lib-arm64.o $(COMMON_O)
@ -50,15 +50,15 @@ Nat = $(if $X,no,)
Cbt = $(Nat)$(subst yes,,$(CONFIG_backtrace)) Cbt = $(Nat)$(subst yes,,$(CONFIG_backtrace))
Cbc = $(Cbt)$(subst yes,,$(CONFIG_bcheck)) Cbc = $(Cbt)$(subst yes,,$(CONFIG_bcheck))
$(Nat)COMMON_O += runmain.o run_nostdlib.o tcov.o $(Nat)COMMON_O += runmain.o tcov.o
$(Cbt)COMMON_O += bt-exe.o bt-log.o $(Cbt)COMMON_O += bt-exe.o bt-log.o
$(Cbt)WIN_O += bt-dll.o $(Cbt)WIN_O += bt-dll.o
$(Cbc)COMMON_O += bcheck.o $(Cbc)COMMON_O += bcheck.o
# not in libtcc1.a # not in libtcc1.a
EXTRA_O = runmain.o run_nostdlib.o bt-exe.o bt-dll.o bt-log.o bcheck.o get_pc_thunk.o EXTRA_O = runmain.o bt-exe.o bt-dll.o bt-log.o bcheck.o
OBJ-i386 = $(I386_O) $(LIN_O) OBJ-i386 = $(I386_O) pic86.o $(LIN_O)
OBJ-x86_64 = $(X86_64_O) $(LIN_O) OBJ-x86_64 = $(X86_64_O) $(LIN_O)
OBJ-x86_64-osx = $(X86_64_O) $(OSX_O) OBJ-x86_64-osx = $(X86_64_O) $(OSX_O)
OBJ-i386-win32 = $(I386_O) chkstk.o $(WIN_O) OBJ-i386-win32 = $(I386_O) chkstk.o $(WIN_O)
@ -90,9 +90,6 @@ $(X)%.o : %.c $(TCC)
$(X)%.o : %.S $(TCC) $(X)%.o : %.S $(TCC)
$S$(XCC) -c $< -o $@ $(XFLAGS) $S$(XCC) -c $< -o $@ $(XFLAGS)
$(TOP)/%.o : %.S $(TCC)
$S$(XCC) -c $< -o $@ $(XFLAGS)
$(TOP)/%.o : %.c $(TCC) $(TOP)/%.o : %.c $(TCC)
$S$(XCC) -c $< -o $@ $(XFLAGS) $S$(XCC) -c $< -o $@ $(XFLAGS)

View File

@ -1,94 +0,0 @@
/* ------------------------------------------------------------- */
/* support for run_nostdlib() */
// FIXME: implement arm64 assembler
#if defined(__aarch64__)
#define USE_ARM64_ASM
static void *alloca_arm64(unsigned long);
__asm__(
#ifdef __leading_underscore
"_alloca_arm64:\n\t"
#else
"alloca_arm64:\n\t"
#endif
".int 0x91003c00\n\t" // add x0, x0, #15
".int 0x927cec00\n\t" // and x0, x0, #-16
".int 0xcb2063ff\n\t" // sub sp, sp, x0
".int 0x910003e0\n\t" // mov x0, sp
".int 0xd65f03c0" // ret
);
static void goto_arm64(void *start);
__asm__(
#ifdef __leading_underscore
"_goto_arm64:\n\t"
#else
"goto_arm64:\n\t"
#endif
".int 0xd61f0000" // br x0
);
#endif
void _run_nostdlib(void *start, int argc, char **argv, char **envp)
{
#if !defined(_WIN32)
int i, n = 1;
unsigned long l;
char **sp, **e = envp;
if (envp)
while (*e++)
n++;
l = (((unsigned long) argc + n + 2 + 1) & -2) * sizeof(char *);
/* nostdlib so avoid alloca() */
/* also code below will be removed because compiler detects dead store */
#if defined(USE_ARM64_ASM)
sp = alloca_arm64(l);
#else
#if defined(__aarch64__)
__asm__("sub sp, sp, %1\n"
"\tmov %0, sp"
#elif defined(__arm__)
__asm__("sub sp, sp, %1\n"
"\tmov %0, sp"
#elif defined(__i386__)
__asm("sub %1, %%esp\n"
"\tmov %%esp, %0"
#elif defined(__riscv)
__asm__("sub sp, sp, %1\n"
"\tmv %0, sp"
#elif defined(__x86_64__)
__asm__("subq %1, %%rsp\n"
"\tmovq %%rsp, %0"
#endif
: "=r" (sp)
: "r" (l));
#endif
/* create sysv memory layout: argc, argv[], NULL, envp[], NULL */
sp[0] = (char *) (__SIZE_TYPE__) argc;
for (i = 0; i < argc; i++)
sp[i + 1] = argv[i];
sp[argc + 1] = (char *) 0;
if (envp)
for (i = 0; i < n; i++)
sp[i + argc + 2] = envp[i];
else
sp[argc + 2] = (char *) 0;
#endif
/* goto *start does not work for clang. Use assembly. */
#if defined(USE_ARM64_ASM)
goto_arm64(start);
#else
#if defined(__aarch64__)
__asm__("br %0" : : "r" (start));
#elif defined(__arm__)
__asm__("mov pc, %0" : : "r" (start));
#elif defined(__i386__)
__asm__("jmp *%0" : : "r" (start));
#elif defined(__riscv)
__asm__("jalr %0" : : "r" (start));
#elif defined(__x86_64__)
__asm__("jmp *%0" : : "r" (start));
#endif
#endif
}

View File

@ -1899,13 +1899,8 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv)
args_parser_add_file(s, r, s->filetype); args_parser_add_file(s, r, s->filetype);
empty = 0; empty = 0;
dorun: dorun:
if (run) { if (run)
/* tcc -run <file> <args...> */ break;
if (tcc_set_options(s, run) < 0)
return -1;
x = 0;
goto extra_action;
}
continue; continue;
} }
/* Also allow "tcc <files...> -run -- <args...>" */ /* Also allow "tcc <files...> -run -- <args...>" */
@ -2219,6 +2214,12 @@ unsupported_option:
} }
if (s->link_optind < s->link_argc) if (s->link_optind < s->link_argc)
return tcc_error_noabort("argument to '-Wl,%s' is missing", s->link_argv[s->link_optind]); return tcc_error_noabort("argument to '-Wl,%s' is missing", s->link_argv[s->link_optind]);
if (run) {
if (*run && tcc_set_options(s, run) < 0)
return -1;
x = 0;
goto extra_action;
}
if (!empty) if (!empty)
return 0; return 0;
if (s->verbose == 2) if (s->verbose == 2)

View File

@ -98,11 +98,8 @@ ST_FUNC void g(int c)
if (nocode_wanted) if (nocode_wanted)
return; return;
ind1 = ind + 1; ind1 = ind + 1;
if ((unsigned)ind1 > cur_text_section->data_allocated) { if (ind1 > cur_text_section->data_allocated)
if (ind1 < 0)
tcc_error("program too big");
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
}
cur_text_section->data[ind] = c; cur_text_section->data[ind] = c;
ind = ind1; ind = ind1;
} }

View File

@ -115,11 +115,8 @@ ST_FUNC void o(unsigned int c)
int ind1 = ind + 4; int ind1 = ind + 4;
if (nocode_wanted) if (nocode_wanted)
return; return;
if ((unsigned)ind1 > cur_text_section->data_allocated) { if (ind1 > cur_text_section->data_allocated)
if (ind1 < 0)
tcc_error("program too big");
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
}
write32le(cur_text_section->data + ind, c); write32le(cur_text_section->data + ind, c);
ind = ind1; ind = ind1;
} }

View File

@ -684,17 +684,14 @@ static void asm_parse_directive(TCCState *s1, int global)
next(); next();
asm_expr(s1, &e); asm_expr(s1, &e);
n = e.v; n = e.v;
if (n != e.v || n < 0)
range:
tcc_error(".org out of range");
esym = elfsym(e.sym); esym = elfsym(e.sym);
if (esym) { if (esym) {
if (esym->st_shndx != cur_text_section->sh_num) if (esym->st_shndx != cur_text_section->sh_num)
expect("constant or same-section symbol"); expect("constant or same-section symbol");
n += esym->st_value; n += esym->st_value;
if (n < esym->st_value)
goto range;
} }
if (n < 0 || n > 0x100000)
tcc_error(".org out of range");
if (n < ind) if (n < ind)
tcc_error("attempt to .org backwards"); tcc_error("attempt to .org backwards");
v = 0; v = 0;
@ -719,8 +716,8 @@ static void asm_parse_directive(TCCState *s1, int global)
do { do {
Sym *sym; Sym *sym;
next(); next();
if (tok < TOK_IDENT || tok >= SYM_FIRST_ANOM) if (tok < TOK_IDENT)
tcc_error("Illegal symbol %s", get_tok_str(tok1, NULL)); expect("identifier");
sym = get_asm_sym(tok, NULL); sym = get_asm_sym(tok, NULL);
if (tok1 != TOK_ASMDIR_hidden) if (tok1 != TOK_ASMDIR_hidden)
sym->type.t &= ~VT_STATIC; sym->type.t &= ~VT_STATIC;
@ -816,15 +813,12 @@ static void asm_parse_directive(TCCState *s1, int global)
{ {
Sym *sym; Sym *sym;
tok1 = tok;
next(); next();
if (tok < TOK_IDENT || tok >= SYM_FIRST_ANOM) if (tok < TOK_IDENT)
goto nolab; expect("identifier");
sym = asm_label_find(tok); sym = asm_label_find(tok);
if (!sym) { if (!sym)
nolab: tcc_error("label not found: %s", get_tok_str(tok, NULL));
tcc_error("label not found: %s", get_tok_str(tok1, NULL));
}
/* XXX .size name,label2-label1 */ /* XXX .size name,label2-label1 */
tcc_warning_c(warn_unsupported)("ignoring .size %s,*", get_tok_str(tok, NULL)); tcc_warning_c(warn_unsupported)("ignoring .size %s,*", get_tok_str(tok, NULL));
next(); next();
@ -840,10 +834,9 @@ static void asm_parse_directive(TCCState *s1, int global)
const char *newtype; const char *newtype;
int st_type; int st_type;
tok1 = tok;
next(); next();
if (tok < TOK_IDENT || tok >= SYM_FIRST_ANOM) if (tok < TOK_IDENT)
tcc_error("Illegal symbol %s", get_tok_str(tok1, NULL)); expect("identifier");
sym = get_asm_sym(tok, NULL); sym = get_asm_sym(tok, NULL);
next(); next();
skip(','); skip(',');
@ -1192,7 +1185,7 @@ static void subst_asm_operands(ASMOperand *operands, int nb_operands,
modifier = *str++; modifier = *str++;
index = find_constraint(operands, nb_operands, str, &str); index = find_constraint(operands, nb_operands, str, &str);
if (index < 0) if (index < 0)
error: error:
tcc_error("invalid operand reference after %%"); tcc_error("invalid operand reference after %%");
op = &operands[index]; op = &operands[index];
if (modifier == 'l') { if (modifier == 'l') {

View File

@ -1840,9 +1840,6 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
tcc_add_dll(s1, TCC_LIBGCC, AFF_PRINT_ERROR); tcc_add_dll(s1, TCC_LIBGCC, AFF_PRINT_ERROR);
} }
#endif #endif
#if defined CONFIG_TCC_PIC && defined TCC_TARGET_I386
tcc_add_support(s1, "get_pc_thunk.o");
#endif
#if defined TCC_TARGET_ARM && TARGETOS_FreeBSD #if defined TCC_TARGET_ARM && TARGETOS_FreeBSD
tcc_add_library(s1, "gcc_s"); // unwind code tcc_add_library(s1, "gcc_s"); // unwind code
#endif #endif
@ -3103,9 +3100,6 @@ LIBTCCAPI int elf_output_obj(TCCState *s1, const char *filename)
{ {
Section *s; Section *s;
int i, ret, file_offset; int i, ret, file_offset;
for(i = 1; i < s1->nb_sections; i++)
if (s1->sections[i] == NULL)
return -2; /* debugging and TCC_OUTPUT_MEMORY and do_debug = 0 */
/* Allocate strings for section names */ /* Allocate strings for section names */
alloc_sec_names(s1, 1); alloc_sec_names(s1, 1);
file_offset = (sizeof (ElfW(Ehdr)) + 3) & -4; file_offset = (sizeof (ElfW(Ehdr)) + 3) & -4;

View File

@ -3589,8 +3589,7 @@ static void cast_error(CType *st, CType *dt)
static void verify_assign_cast(CType *dt) static void verify_assign_cast(CType *dt)
{ {
CType *st, *type1, *type2; CType *st, *type1, *type2;
Sym *sym; int dbt, sbt, qualwarn, lvl;
int dbt, sbt, qualwarn, lvl, compat;
st = &vtop->type; /* source type */ st = &vtop->type; /* source type */
dbt = dt->t & VT_BTYPE; dbt = dt->t & VT_BTYPE;
@ -3644,29 +3643,8 @@ static void verify_assign_cast(CType *dt)
base types, though, in particular for unsigned enums base types, though, in particular for unsigned enums
and signed int targets. */ and signed int targets. */
} else { } else {
compat = 0; tcc_warning("assignment from incompatible pointer type");
/* Don't warn if the source struct (recursively) contains break;
destination struct as the first member. */
if (dbt == VT_STRUCT && sbt == VT_STRUCT
&& !IS_UNION(type2->t)
) {
sym = type2->ref->next;
while (sym != NULL && (sym->type.t & VT_BTYPE) == VT_STRUCT
) {
if (is_compatible_unqualified_types(type1, &sym->type)
) {
compat = 1;
break;
}
if (IS_UNION(sym->type.t))
break;
sym = sym->type.ref->next;
}
}
if( !compat ) {
tcc_warning("assignment from incompatible pointer type");
break;
}
} }
} }
if (qualwarn) if (qualwarn)
@ -7837,9 +7815,6 @@ static void init_putv(init_params *p, CType *type, unsigned long c)
ElfW_Rel *rel; ElfW_Rel *rel;
esym = elfsym(vtop->sym); esym = elfsym(vtop->sym);
ssec = tcc_state->sections[esym->st_shndx]; ssec = tcc_state->sections[esym->st_shndx];
if (esym->st_value + (int)vtop->c.i + size > ssec->data_offset)
section_add(ssec, esym->st_value + (int)vtop->c.i +
size - ssec->data_offset, 1);
memmove (ptr, ssec->data + esym->st_value + (int)vtop->c.i, size); memmove (ptr, ssec->data + esym->st_value + (int)vtop->c.i, size);
if (ssec->reloc) { if (ssec->reloc) {
/* We need to copy over all memory contents, and that /* We need to copy over all memory contents, and that
@ -8745,13 +8720,8 @@ static int decl(int l)
while (1) { /* iterate thru each declaration */ while (1) { /* iterate thru each declaration */
type = btype; type = btype;
ad = adbase; ad = adbase;
if (l == VT_CMP) { type_decl(&type, &ad, &v, l == VT_CMP ? TYPE_DIRECT | TYPE_PARAM : TYPE_DIRECT);
type_decl(&type, &ad, &v, TYPE_DIRECT | TYPE_PARAM);
} else {
type_decl(&type, &ad, &v, TYPE_DIRECT);
}
/*ptype("decl", &type, v);*/ /*ptype("decl", &type, v);*/
if ((type.t & VT_BTYPE) == VT_FUNC) { if ((type.t & VT_BTYPE) == VT_FUNC) {
if ((type.t & VT_STATIC) && (l != VT_CONST)) if ((type.t & VT_STATIC) && (l != VT_CONST))
tcc_error("function without file scope cannot be static"); tcc_error("function without file scope cannot be static");

367
tccpp.c
View File

@ -115,89 +115,49 @@ ST_FUNC void expect(const char *msg)
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* Custom allocator for tiny objects */ /* Custom allocator for tiny objects */
#define PP_ALLOC_INSERT(a) (a)->next = &pp_allocs; \
(a)->prev = pp_allocs.prev; \
pp_allocs.prev->next = (a); \
pp_allocs.prev = (a);
#define PP_ALLOC_REMOVE(a) (a)->next->prev = (a)->prev; \
(a)->prev->next = (a)->next;
typedef struct pp_alloc_t {
struct pp_alloc_t *next, *prev;
} pp_alloc_t;
static pp_alloc_t pp_allocs;
#define USE_TAL #define USE_TAL
#ifndef USE_TAL #ifndef USE_TAL /* may cause memory leaks after errors */
#define tal_free(al, p) tcc_free_impl(p) #define tal_free(al, p) tcc_free(p)
#define tal_realloc(al, p, size) tcc_realloc_impl(p, size) #define tal_realloc(al, p, size) tcc_realloc(p, size)
#define tal_new(a,b,c) #define tal_new(a,b)
#define tal_delete(a) #define tal_delete(a)
static void tcc_free_impl(void *p)
{
if (p) {
pp_alloc_t *alloc = ((pp_alloc_t *)p) - 1;
PP_ALLOC_REMOVE(alloc);
tcc_free(alloc);
}
}
static void *tcc_realloc_impl(void *p, unsigned size)
{
pp_alloc_t *alloc = NULL;
if (p) {
alloc = ((pp_alloc_t *)p) - 1;
PP_ALLOC_REMOVE(alloc);
}
if (size) {
alloc = tcc_realloc(alloc, size + sizeof(pp_alloc_t));
PP_ALLOC_INSERT(alloc);
return alloc + 1;
}
tcc_free(alloc);
return NULL;
}
#else #else
#if !defined(MEM_DEBUG) #if !defined(MEM_DEBUG)
#define tal_free(al, p) tal_free_impl(al, p) #define tal_free(al, p) tal_free_impl(al, p)
#define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size) #define tal_realloc(al, p, size) tal_realloc_impl(al, p, size)
#define TAL_DEBUG_PARAMS #define TAL_DEBUG_PARAMS
#else #else
#define TAL_DEBUG MEM_DEBUG #define TAL_DEBUG MEM_DEBUG
//#define TAL_INFO 1 /* collect and dump allocators stats */ //#define TAL_INFO 1 /* collect and dump allocators stats */
#define tal_free(al, p) tal_free_impl(al, p, __FILE__, __LINE__) #define tal_free(al, p) tal_free_impl(al, p, __FILE__, __LINE__)
#define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size, __FILE__, __LINE__) #define tal_realloc(al, p, size) tal_realloc_impl(al, p, size, __FILE__, __LINE__)
#define TAL_DEBUG_PARAMS , const char *file, int line #define TAL_DEBUG_PARAMS , const char *sfile, int sline
#endif #endif
#define TOKSYM_TAL_SIZE (768 * 1024) /* allocator for tiny TokenSym in table_ident */ #define TOKSYM_TAL_SIZE (256 * 1024) /* allocator for TokenSym in table_ident */
#define TOKSTR_TAL_SIZE (768 * 1024) /* allocator for tiny TokenString instances */ #define TOKSTR_TAL_SIZE (256 * 1024) /* allocator for TokenString instances */
#define TOKSYM_TAL_LIMIT 256 /* prefer unique limits to distinguish allocators debug msgs */
#define TOKSTR_TAL_LIMIT 1024 /* 256 * sizeof(int) */
typedef struct TinyAlloc { typedef struct TinyAlloc {
unsigned limit;
unsigned size;
uint8_t *buffer;
uint8_t *p; uint8_t *p;
unsigned nb_allocs; uint8_t *bufend;
struct TinyAlloc *next, *top; struct TinyAlloc *next;
#ifdef TAL_INFO unsigned nb_allocs;
unsigned nb_peak; unsigned size;
unsigned nb_total; #if TAL_INFO
unsigned nb_missed; unsigned nb_peak;
unsigned nb_total;
uint8_t *peak_p; uint8_t *peak_p;
#endif #endif
union {
uint8_t buffer[1];
size_t _aligner_;
};
} TinyAlloc; } TinyAlloc;
typedef struct tal_header_t { typedef struct tal_header_t {
size_t size; /* word align */ size_t size; /* word align */
#ifdef TAL_DEBUG #if TAL_DEBUG
int line_num; /* negative line_num used for double free check */ int line_num; /* negative line_num used for double free check */
char file_name[40]; char file_name[40];
#endif #endif
@ -208,33 +168,39 @@ typedef struct tal_header_t {
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
static TinyAlloc *tal_new(TinyAlloc **pal, unsigned limit, unsigned size) static TinyAlloc *tal_new(TinyAlloc **pal, unsigned size)
{ {
TinyAlloc *al = tcc_mallocz(sizeof(TinyAlloc)); TinyAlloc *al = tcc_malloc(sizeof(TinyAlloc) - sizeof (size_t) + size);
al->p = al->buffer = tcc_malloc(size); al->p = al->buffer;
al->limit = limit; al->bufend = al->buffer + size;
al->size = size; al->nb_allocs = 0;
if (pal) *pal = al; al->next = *pal, *pal = al;
al->size = al->next ? al->next->size : size;
#if TAL_INFO
al->nb_peak = 0;
al->nb_total = 0;
al->peak_p = al->p;
#endif
return al; return al;
} }
static void tal_delete(TinyAlloc *al) static void tal_delete(TinyAlloc **pal)
{ {
TinyAlloc *next; TinyAlloc *al = *pal, *next;
tail_call: #if TAL_INFO
if (!al) fprintf(stderr, "tal_delete (&tok%s_alloc):\n", pal == &toksym_alloc ? "sym" : "str");
return;
#ifdef TAL_INFO
fprintf(stderr, "limit %4d size %7d nb_peak %5d nb_total %7d nb_missed %5d usage %5.1f%%\n",
al->limit, al->size, al->nb_peak, al->nb_total, al->nb_missed,
(al->peak_p - al->buffer) * 100.0 / al->size);
#endif #endif
tail_call:
#if TAL_DEBUG && TAL_DEBUG != 3 /* do not check TAL leaks with -DMEM_DEBUG=3 */ #if TAL_DEBUG && TAL_DEBUG != 3 /* do not check TAL leaks with -DMEM_DEBUG=3 */
#if TAL_INFO
fprintf(stderr, " size %7d nb_peak %5d nb_total %6d usage %5.1f%%\n",
al->bufend - al->buffer, al->nb_peak, al->nb_total,
(al->peak_p - al->buffer) * 100.0 / (al->bufend - al->buffer));
#endif
if (al->nb_allocs > 0) { if (al->nb_allocs > 0) {
uint8_t *p; uint8_t *p;
fprintf(stderr, "TAL_DEBUG: memory leak %d chunk(s) (limit= %d)\n", fprintf(stderr, "TAL_DEBUG: memory leak %d chunk(s)\n", al->nb_allocs);
al->nb_allocs, al->limit);
p = al->buffer; p = al->buffer;
while (p < al->p) { while (p < al->p) {
tal_header_t *header = (tal_header_t *)p; tal_header_t *header = (tal_header_t *)p;
@ -250,40 +216,45 @@ tail_call:
} }
#endif #endif
next = al->next; next = al->next;
tcc_free(al->buffer);
tcc_free(al); tcc_free(al);
al = next; al = next;
goto tail_call; if (al)
goto tail_call;
*pal = al;
} }
static void tal_free_impl(TinyAlloc *al, void *p TAL_DEBUG_PARAMS) static void tal_free_impl(TinyAlloc **pal, void *p TAL_DEBUG_PARAMS)
{ {
TinyAlloc *al, **top = pal;
tal_header_t *header;
if (!p) if (!p)
return; return;
tail_call: header = (tal_header_t *)p - 1;
if (al->buffer <= (uint8_t *)p && (uint8_t *)p < al->buffer + al->size) { #if TAL_DEBUG
#ifdef TAL_DEBUG if (header->line_num < 0) {
tal_header_t *header = (((tal_header_t *)p) - 1); fprintf(stderr, "%s:%d: TAL_DEBUG: double frees chunk from\n",
if (header->line_num < 0) { sfile, sline);
fprintf(stderr, "%s:%d: TAL_DEBUG: double frees chunk from\n", fprintf(stderr, "%s:%d: %d bytes\n",
file, line); header->file_name, (int)-header->line_num, (int)header->size);
fprintf(stderr, "%s:%d: %d bytes\n", } else
header->file_name, (int)-header->line_num, (int)header->size); header->line_num = -header->line_num;
} else
header->line_num = -header->line_num;
#endif #endif
al->nb_allocs--; al = *pal;
if (!al->nb_allocs) while ((uint8_t*)p < al->buffer || (uint8_t*)p > al->bufend)
al = *(pal = &al->next);
if (0 == --al->nb_allocs) {
*pal = al->next;
if ((al->bufend - al->buffer) > al->size) {
//fprintf(stderr, "free big tal: %u\n", header->size);
tcc_free(al);
} else {
/* reset and move to front */
al->p = al->buffer; al->p = al->buffer;
} else if (al->next) { al->next = *top, *top = al;
al = al->next; }
goto tail_call; } else if ((uint8_t*)p + header->size == al->p) {
} al->p = (uint8_t*)header;
else {
pp_alloc_t *alloc = ((pp_alloc_t *)p) - 1;
PP_ALLOC_REMOVE(alloc);
tcc_free(alloc);
} }
} }
@ -291,112 +262,66 @@ static void *tal_realloc_impl(TinyAlloc **pal, void *p, unsigned size TAL_DEBUG_
{ {
tal_header_t *header; tal_header_t *header;
void *ret; void *ret;
int is_own; unsigned adj_size = TAL_ALIGN(size) + sizeof(tal_header_t);
unsigned adj_size = TAL_ALIGN(size);
TinyAlloc *al = *pal; TinyAlloc *al = *pal;
tail_call: if (p) {
is_own = (al->buffer <= (uint8_t *)p && (uint8_t *)p < al->buffer + al->size); /* reallpc case */
if ((!p || is_own) && size <= al->limit) { while ((uint8_t*)p < al->buffer || (uint8_t*)p > al->bufend)
if (al->p - al->buffer + adj_size + sizeof(tal_header_t) < al->size) { al = al->next;
header = (tal_header_t *)al->p; header = (tal_header_t *)p - 1;
header->size = adj_size; if ((uint8_t*)p + header->size == al->p)
#ifdef TAL_DEBUG al->p = (uint8_t*)header; /* maybe reuse */
{ int ofs = strlen(file) + 1 - sizeof header->file_name; if (al->p + adj_size > al->bufend) {
strcpy(header->file_name, file + (ofs > 0 ? ofs : 0)); ret = tal_realloc(pal, 0, size);
header->line_num = line; } memcpy(ret, p, header->size);
#endif tal_free(pal, p);
ret = al->p + sizeof(tal_header_t);
al->p += adj_size + sizeof(tal_header_t);
if (is_own) {
header = (((tal_header_t *)p) - 1);
if (p) memcpy(ret, p, header->size);
#ifdef TAL_DEBUG
header->line_num = -header->line_num;
#endif
} else {
al->nb_allocs++;
}
#ifdef TAL_INFO
if (al->nb_peak < al->nb_allocs)
al->nb_peak = al->nb_allocs;
if (al->peak_p < al->p)
al->peak_p = al->p;
al->nb_total++;
#endif
return ret; return ret;
} else if (is_own) { } else if (al->p != (uint8_t*)header) {
al->nb_allocs--; memcpy((tal_header_t*)al->p + 1, p, header->size);
ret = tal_realloc(*pal, 0, size); #if TAL_DEBUG
header = (((tal_header_t *)p) - 1);
if (p) memcpy(ret, p, header->size);
#ifdef TAL_DEBUG
header->line_num = -header->line_num; header->line_num = -header->line_num;
#endif #endif
return ret;
} }
if (al->next) {
al = al->next;
} else {
TinyAlloc *bottom = al, *next = al->top ? al->top : al;
al = tal_new(pal, next->limit, next->size * 2);
al->next = next;
bottom->top = al;
}
goto tail_call;
}
if (is_own) {
pp_alloc_t *alloc;
al->nb_allocs--;
alloc = tcc_malloc(size + sizeof(pp_alloc_t));
PP_ALLOC_INSERT(alloc);
ret = alloc + 1;
header = (((tal_header_t *)p) - 1);
if (p) memcpy(ret, p, header->size);
#ifdef TAL_DEBUG
header->line_num = -header->line_num;
#endif
} else if (al->next) {
al = al->next;
goto tail_call;
} else { } else {
pp_alloc_t *alloc = NULL; /* new alloc case */
while (al->p + adj_size > al->bufend) {
if (p) { al = al->next;
alloc = ((pp_alloc_t *)p) - 1; if (!al) {
PP_ALLOC_REMOVE(alloc); unsigned new_size = (*pal)->size;
} if (adj_size > new_size) {
if (size) { new_size = adj_size;
alloc = tcc_realloc(alloc, size + sizeof(pp_alloc_t)); //fprintf(stderr, "%s:%d: alloc big tal: %u\n", file->filename, file->line_num, adj_size - sizeof(tal_header_t));
PP_ALLOC_INSERT(alloc); }
ret = alloc + 1; al = tal_new(pal, new_size);
} break;
else { }
tcc_free(alloc); }
ret = NULL; al->nb_allocs++;
} }
header = (tal_header_t *)al->p;
header->size = adj_size - sizeof(tal_header_t);
al->p += adj_size;
ret = header + 1;
#if TAL_DEBUG
{
int ofs = strlen(sfile) + 1 - sizeof header->file_name;
strcpy(header->file_name, sfile + (ofs > 0 ? ofs : 0));
header->line_num = sline;
#if TAL_INFO
if (al->nb_peak < al->nb_allocs)
al->nb_peak = al->nb_allocs;
if (al->peak_p < al->p)
al->peak_p = al->p;
al->nb_total++;
#endif
} }
#ifdef TAL_INFO
al->nb_missed++;
#endif #endif
return ret; return ret;
} }
#endif /* USE_TAL */ #endif /* USE_TAL */
static void tal_alloc_init(void)
{
pp_allocs.next = pp_allocs.prev = &pp_allocs;
}
static void tal_alloc_free(void)
{
while (pp_allocs.next != &pp_allocs)
tal_free(toksym_alloc /* dummy */, pp_allocs.next + 1);
}
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* CString handling */ /* CString handling */
static void cstr_realloc(CString *cstr, int new_size) static void cstr_realloc(CString *cstr, int new_size)
@ -550,7 +475,7 @@ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
table_ident = ptable; table_ident = ptable;
} }
ts = tal_realloc(toksym_alloc, 0, sizeof(TokenSym) + len); ts = tal_realloc(&toksym_alloc, 0, sizeof(TokenSym) + len);
table_ident[i] = ts; table_ident[i] = ts;
ts->tok = tok_ident++; ts->tok = tok_ident++;
ts->sym_define = NULL; ts->sym_define = NULL;
@ -1084,20 +1009,20 @@ ST_INLN void tok_str_new(TokenString *s)
ST_FUNC TokenString *tok_str_alloc(void) ST_FUNC TokenString *tok_str_alloc(void)
{ {
TokenString *str = tal_realloc(tokstr_alloc, 0, sizeof *str); TokenString *str = tal_realloc(&tokstr_alloc, 0, sizeof *str);
tok_str_new(str); tok_str_new(str);
return str; return str;
} }
ST_FUNC void tok_str_free_str(int *str) ST_FUNC void tok_str_free_str(int *str)
{ {
tal_free(tokstr_alloc, str); tal_free(&tokstr_alloc, str);
} }
ST_FUNC void tok_str_free(TokenString *str) ST_FUNC void tok_str_free(TokenString *str)
{ {
tok_str_free_str(str->str); tok_str_free_str(str->str);
tal_free(tokstr_alloc, str); tal_free(&tokstr_alloc, str);
} }
ST_FUNC int *tok_str_realloc(TokenString *s, int new_size) ST_FUNC int *tok_str_realloc(TokenString *s, int new_size)
@ -1110,7 +1035,7 @@ ST_FUNC int *tok_str_realloc(TokenString *s, int new_size)
while (size < new_size) while (size < new_size)
size = size * 2; size = size * 2;
if (size > s->allocated_len) { if (size > s->allocated_len) {
str = tal_realloc(tokstr_alloc, s->str, size * sizeof(int)); str = tal_realloc(&tokstr_alloc, s->str, size * sizeof(int));
s->allocated_len = size; s->allocated_len = size;
s->str = str; s->str = str;
} }
@ -2550,7 +2475,7 @@ static void parse_number(const char *p)
} }
} }
} else { } else {
unsigned long long n = 0, n1 = 0; unsigned long long n, n1;
int lcount, ucount, ov = 0; int lcount, ucount, ov = 0;
const char *p1; const char *p1;
@ -2561,6 +2486,7 @@ static void parse_number(const char *p)
b = 8; b = 8;
q++; q++;
} }
n = 0;
while(1) { while(1) {
t = *q++; t = *q++;
/* no need for checks except for base 10 / 8 errors */ /* no need for checks except for base 10 / 8 errors */
@ -2574,23 +2500,13 @@ static void parse_number(const char *p)
t = t - '0'; t = t - '0';
if (t >= b) if (t >= b)
tcc_error("invalid digit"); tcc_error("invalid digit");
n1 = n;
n = n * b + t; n = n * b + t;
if (!ov) { /* detect overflow */
/* detect overflow */ if (n1 >= 0x1000000000000000ULL && n / b != n1)
if (n1 >= 0x1000000000000000ULL && n / b != n1) ov = 1;
ov = 1;
else
n1 = n;
}
} }
#ifdef TCC_CUT_ON_INTEGER_LITERAL_OVERFLOW
/* On integer literal overflow use the most significant digits before
the overflow happened. Effectively this cuts the 0x1000000000000000
from above down to 0x10000000 and allows to bootstrap tcc with 32 bit
arithmetic. */
if (ov)
n = n1;
#endif
/* Determine the characteristics (unsigned and/or 64bit) the type of /* Determine the characteristics (unsigned and/or 64bit) the type of
the constant must have according to the constant suffix(es) */ the constant must have according to the constant suffix(es) */
lcount = ucount = 0; lcount = ucount = 0;
@ -3830,9 +3746,8 @@ ST_FUNC void tccpp_new(TCCState *s)
set_idnum(i, IS_ID); set_idnum(i, IS_ID);
/* init allocators */ /* init allocators */
tal_new(&toksym_alloc, TOKSYM_TAL_LIMIT, TOKSYM_TAL_SIZE); tal_new(&toksym_alloc, TOKSYM_TAL_SIZE);
tal_new(&tokstr_alloc, TOKSTR_TAL_LIMIT, TOKSTR_TAL_SIZE); tal_new(&tokstr_alloc, TOKSTR_TAL_SIZE);
tal_alloc_init();
memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *)); memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
memset(s->cached_includes_hash, 0, sizeof s->cached_includes_hash); memset(s->cached_includes_hash, 0, sizeof s->cached_includes_hash);
@ -3840,9 +3755,10 @@ ST_FUNC void tccpp_new(TCCState *s)
cstr_new(&tokcstr); cstr_new(&tokcstr);
cstr_new(&cstr_buf); cstr_new(&cstr_buf);
cstr_realloc(&cstr_buf, STRING_MAX_SIZE); cstr_realloc(&cstr_buf, STRING_MAX_SIZE);
tok_str_new(&unget_buf);
tok_str_realloc(&unget_buf, TOKSTR_MAX_SIZE);
tok_str_new(&tokstr_buf); tok_str_new(&tokstr_buf);
tok_str_realloc(&tokstr_buf, TOKSTR_MAX_SIZE); tok_str_realloc(&tokstr_buf, TOKSTR_MAX_SIZE);
tok_str_new(&unget_buf);
tok_ident = TOK_IDENT; tok_ident = TOK_IDENT;
p = tcc_keywords; p = tcc_keywords;
@ -3876,8 +3792,8 @@ ST_FUNC void tccpp_delete(TCCState *s)
n = tok_ident - TOK_IDENT; n = tok_ident - TOK_IDENT;
if (n > total_idents) if (n > total_idents)
total_idents = n; total_idents = n;
for(i = 0; i < n; i++) for (i = n; --i >= 0;)
tal_free(toksym_alloc, table_ident[i]); tal_free(&toksym_alloc, table_ident[i]);
tcc_free(table_ident); tcc_free(table_ident);
table_ident = NULL; table_ident = NULL;
@ -3888,11 +3804,8 @@ ST_FUNC void tccpp_delete(TCCState *s)
tok_str_free_str(unget_buf.str); tok_str_free_str(unget_buf.str);
/* free allocators */ /* free allocators */
tal_alloc_free(); tal_delete(&toksym_alloc);
tal_delete(toksym_alloc); tal_delete(&tokstr_alloc);
toksym_alloc = NULL;
tal_delete(tokstr_alloc);
tokstr_alloc = NULL;
} }
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */

View File

@ -120,10 +120,7 @@ static int rt_mem(TCCState *s1, int size)
unlink(tmpfname); unlink(tmpfname);
ftruncate(fd, size); ftruncate(fd, size);
ptr = mmap(NULL, size * 2, PROT_READ|PROT_EXEC|(s1->do_debug ? PROT_WRITE : 0), MAP_SHARED, fd, 0); ptr = mmap(NULL, size * 2, PROT_READ|PROT_EXEC, MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED)
/* Some targets do not support PROT_EXEC + PROT_WRITE */
ptr = mmap(NULL, size * 2, PROT_READ|PROT_EXEC, MAP_SHARED, fd, 0);
/* mmap RW memory at fixed distance */ /* mmap RW memory at fixed distance */
prw = mmap((char*)ptr + size, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, 0); prw = mmap((char*)ptr + size, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, 0);
close(fd); close(fd);
@ -224,14 +221,11 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
return 0; return 0;
tcc_add_symbol(s1, "__rt_exit", rt_exit); tcc_add_symbol(s1, "__rt_exit", rt_exit);
if (s1->nostdlib) { s1->run_main = "_runmain", top_sym = "main";
tcc_add_support(s1, "run_nostdlib.o"); if (s1->elf_entryname)
s1->run_main = top_sym = s1->elf_entryname ? s1->elf_entryname : "_start"; s1->run_main = top_sym = s1->elf_entryname;
} else { tcc_add_support(s1, "runmain.o");
tcc_add_support(s1, "runmain.o");
s1->run_main = "_runmain";
top_sym = "main";
}
if (tcc_relocate(s1) < 0) if (tcc_relocate(s1) < 0)
return -1; return -1;
@ -255,19 +249,10 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
ret = tcc_setjmp(s1, main_jb, tcc_get_symbol(s1, top_sym)); ret = tcc_setjmp(s1, main_jb, tcc_get_symbol(s1, top_sym));
if (0 == ret) { if (0 == ret) {
if (s1->nostdlib) { ret = prog_main(argc, argv, envp);
void (*run_nostdlib)(void *start, int argc, char **argv, char **envp); } else if (RT_EXIT_ZERO == ret) {
run_nostdlib = (void *)get_sym_addr(s1, "_run_nostdlib", 1, 1);
if ((addr_t)-1 == (addr_t)run_nostdlib)
return -1;
run_nostdlib(prog_main, argc, argv, envp); /* never returns */
}
else
ret = prog_main(argc, argv, envp);
}
else if (RT_EXIT_ZERO == ret)
ret = 0; ret = 0;
}
if (s1->dflag & 16 && ret) /* tcc -dt -run ... */ if (s1->dflag & 16 && ret) /* tcc -dt -run ... */
fprintf(s1->ppfp, "[returns %d]\n", ret), fflush(s1->ppfp); fprintf(s1->ppfp, "[returns %d]\n", ret), fflush(s1->ppfp);

View File

@ -551,84 +551,4 @@ int main(int argc, char **argv)
} }
#elif defined test_jmp_label
int main(void) {
asm goto("jmp %[label]" : : : : label);
}
#elif defined test_void_ternary
int main() {
unsigned long b = 0;
if ((b ? (void)0 : (long long)b))
}
#elif defined test_init_int_string
int fsB = "";
//#elif defined test_constant1
// results differs on 32/64 bits targets
// reports 64: constant expression expected
// reports 32: constant exceeds 32 bit
//e[1.0 < r()
//
//#elif defined test_constant2
// results differs on 32/64 bits targets
// reports 64: constant expression expected
// reports 32: constant exceeds 32 bit
//e[1 < r()-1.
#elif defined test_asm1
asm (".align 8589934592");
#elif defined test_asm2
asm (".balign 8589934592");
#elif defined test_asm3
asm (".global ");
#elif defined test_asm4
asm (".type (a,cr0,digit)");
#elif defined test_asm5
asm (".type $6");
#elif defined test_asm6
asm (".global $-3");
#elif defined test_asm7
asm (".global (dx,0X2D,digit)");
#elif defined test_asm8
asm (".size 0XA");
#elif defined test_asm9
asm (".weak (fs:0)");
#elif defined test_asm10
asm (".align 0");
#elif defined test_asm11
asm (".org 33824993159184");
//#elif defined test_big
// results differs on 32/64 bits targets
// reports 64: error: program too big
// reports 32: memory full
//asm (".org 0x7fffffff");
//asm (".byte 1, 2, 3, 4");
#endif #endif

View File

@ -262,45 +262,3 @@ bar 15 12 34
[test_scope_3] [test_scope_3]
60_errors_and_warnings.c:548: warning: assignment from incompatible pointer type 60_errors_and_warnings.c:548: warning: assignment from incompatible pointer type
60_errors_and_warnings.c:549: error: initialization of incomplete type 60_errors_and_warnings.c:549: error: initialization of incomplete type
[test_jmp_label]
60_errors_and_warnings.c:557: error: invalid operand reference after %
[test_void_ternary]
60_errors_and_warnings.c:564: error: invalid operand types for binary operation
[test_init_int_string]
60_errors_and_warnings.c:569: warning: assignment makes integer from pointer without a cast
[test_asm1]
60_errors_and_warnings.c:584: error: integer out of range 8589934592
[test_asm2]
60_errors_and_warnings.c:588: error: integer out of range 8589934592
[test_asm3]
60_errors_and_warnings.c:592: error: Illegal symbol .global
[test_asm4]
60_errors_and_warnings.c:597: error: Illegal symbol .type
[test_asm5]
60_errors_and_warnings.c:601: error: Illegal symbol .type
[test_asm6]
60_errors_and_warnings.c:605: error: Illegal symbol .global
[test_asm7]
60_errors_and_warnings.c:609: error: Illegal symbol .global
[test_asm8]
60_errors_and_warnings.c:613: error: label not found: .size
[test_asm9]
60_errors_and_warnings.c:617: error: Illegal symbol .weak
[test_asm10]
60_errors_and_warnings.c:620: error: alignment must be a positive power of two
[test_asm11]
60_errors_and_warnings.c:624: error: .org out of range

View File

@ -175,11 +175,8 @@ ST_FUNC void g(int c)
if (nocode_wanted) if (nocode_wanted)
return; return;
ind1 = ind + 1; ind1 = ind + 1;
if ((unsigned)ind1 > cur_text_section->data_allocated) { if (ind1 > cur_text_section->data_allocated)
if (ind1 < 0)
tcc_error("program too big");
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
}
cur_text_section->data[ind] = c; cur_text_section->data[ind] = c;
ind = ind1; ind = ind1;
} }

View File

@ -221,15 +221,13 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
qrel->r_addend = (int)read32le(ptr) + val; qrel->r_addend = (int)read32le(ptr) + val;
qrel++; qrel++;
} }
/* ignore relocation check for stab section */ if ((type == R_X86_64_32 ? val != (unsigned)val : val != (int)val)
if ((stab_section == NULL || /* ignore relocation check for stab section */
addr < stab_section->sh_addr || && (stab_section == NULL ||
addr >= (stab_section->sh_addr + stab_section->data_offset)) && addr < stab_section->sh_addr ||
((type == R_X86_64_32 && addr >= (stab_section->sh_addr + stab_section->data_offset))) {
(unsigned long long)val > 4294967295ULL) || tcc_error_noabort("relocation 'R_X86_64_32[S]' out of range");
(type == R_X86_64_32S && }
((long long)val < -2147483648LL || (long long)val > 2147483647LL))))
tcc_error_noabort("internal error: relocation %d failed", type);
add32le(ptr, val); add32le(ptr, val);
break; break;
@ -260,7 +258,7 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
/* ignore overflow with undefined weak symbols */ /* ignore overflow with undefined weak symbols */
if (((ElfW(Sym)*)symtab_section->data)[sym_index].st_shndx != SHN_UNDEF) if (((ElfW(Sym)*)symtab_section->data)[sym_index].st_shndx != SHN_UNDEF)
#endif #endif
tcc_error_noabort("internal error: relocation %d failed", type); tcc_error_noabort("relocation '%d' out of range", type);
} }
add32le(ptr, diff); add32le(ptr, diff);
} }