mirror of
git://repo.or.cz/tinycc.git
synced 2026-06-17 15:44:18 +08:00
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
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 from831c3fa184tccpp.c: - remove code that allows tcc to parse numbers incorrectly (*) from829c848520tccgen.c: - Revert "Relaxed the 'incompatible pointer type' warning a bit" (*) fromd9ec17d334. 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." fromc96f0cad61Remove 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:
parent
518279dc3e
commit
5ec0e6f84b
26
.github/workflows/build.yml
vendored
26
.github/workflows/build.yml
vendored
@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 2
|
||||
steps:
|
||||
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- uses: actions/checkout@v4
|
||||
- name: make & test tcc (x86_64-linux)
|
||||
run: ./configure && make && make test -k
|
||||
|
||||
@ -17,7 +17,7 @@ jobs:
|
||||
runs-on: macos-15-intel
|
||||
timeout-minutes: 2
|
||||
steps:
|
||||
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- uses: actions/checkout@v4
|
||||
- name: make & test tcc (x86_64-osx)
|
||||
run: ./configure && make && make test -k
|
||||
|
||||
@ -25,7 +25,7 @@ jobs:
|
||||
runs-on: macos-15
|
||||
timeout-minutes: 2
|
||||
steps:
|
||||
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- uses: actions/checkout@v4
|
||||
- name: make & test tcc (aarch64-osx)
|
||||
run: ./configure && make && make test -k
|
||||
|
||||
@ -33,7 +33,7 @@ jobs:
|
||||
runs-on: windows-2025
|
||||
timeout-minutes: 6
|
||||
steps:
|
||||
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- uses: actions/checkout@v4
|
||||
- name: make & test tcc (x86_64-win32)
|
||||
shell: cmd
|
||||
run: |
|
||||
@ -44,7 +44,7 @@ jobs:
|
||||
C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-x86_64-gcc"
|
||||
echo ::endgroup::
|
||||
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:
|
||||
arch: amd64
|
||||
- name: build with MSVC (x86_64-win32)
|
||||
@ -61,7 +61,7 @@ jobs:
|
||||
runs-on: windows-2025
|
||||
timeout-minutes: 6
|
||||
steps:
|
||||
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- uses: actions/checkout@v4
|
||||
- name: make & test tcc (i386-win32)
|
||||
shell: cmd
|
||||
run: |
|
||||
@ -72,7 +72,7 @@ jobs:
|
||||
C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-i686-gcc"
|
||||
echo ::endgroup::
|
||||
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:
|
||||
arch: x86
|
||||
- name: build with MSVC (i386-win32)
|
||||
@ -89,8 +89,8 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 8
|
||||
steps:
|
||||
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1
|
||||
- uses: actions/checkout@v4
|
||||
- uses: uraimo/run-on-arch-action@v3
|
||||
name: make & test tcc (armv7-linux)
|
||||
with:
|
||||
arch: armv7
|
||||
@ -107,8 +107,8 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 8
|
||||
steps:
|
||||
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1
|
||||
- uses: actions/checkout@v4
|
||||
- uses: uraimo/run-on-arch-action@v3
|
||||
name: make & test tcc (aarch64-linux)
|
||||
with:
|
||||
arch: aarch64
|
||||
@ -125,8 +125,8 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 8
|
||||
steps:
|
||||
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1
|
||||
- uses: actions/checkout@v4
|
||||
- uses: uraimo/run-on-arch-action@v3
|
||||
name: make & test tcc (riscv64-linux)
|
||||
with:
|
||||
arch: riscv64
|
||||
|
||||
14
Makefile
14
Makefile
@ -24,11 +24,6 @@ CFLAGS += $(CPPFLAGS)
|
||||
VPATH = $(TOPSRC)
|
||||
-LTCC = $(TOP)/$(LIBTCC)
|
||||
|
||||
ifeq ($(CONFIG_pie),yes)
|
||||
CFLAGS += -fPIE
|
||||
LDFLAGS += -pie
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WIN32
|
||||
CFG = -win
|
||||
ifneq ($(CONFIG_static),yes)
|
||||
@ -296,6 +291,11 @@ tcc_p$(EXESUF): $($T_FILES)
|
||||
libtcc.a: $(LIBTCC_OBJ)
|
||||
$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
|
||||
libtcc.so: $(LIBTCC_OBJ)
|
||||
$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" ;
|
||||
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-unx:
|
||||
@ -394,7 +394,7 @@ endif
|
||||
# uninstall
|
||||
uninstall-unx:
|
||||
@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 "$(mandir)/man1/tcc.1" "$(infodir)/tcc-doc.info"
|
||||
@rm -fv "$(docdir)/tcc-doc.html"
|
||||
|
||||
@ -149,11 +149,8 @@ ST_FUNC void g(int c)
|
||||
if (nocode_wanted)
|
||||
return;
|
||||
ind1 = ind + 1;
|
||||
if ((unsigned)ind1 > cur_text_section->data_allocated) {
|
||||
if (ind1 < 0)
|
||||
tcc_error("program too big");
|
||||
if (ind1 > cur_text_section->data_allocated)
|
||||
section_realloc(cur_text_section, ind1);
|
||||
}
|
||||
cur_text_section->data[ind] = c;
|
||||
ind = ind1;
|
||||
}
|
||||
|
||||
@ -257,11 +257,8 @@ void o(uint32_t i)
|
||||
if (!cur_text_section)
|
||||
tcc_error("compiler error! This happens f.ex. if the compiler\n"
|
||||
"can't evaluate constant expressions outside of a function.");
|
||||
if ((unsigned)ind1 > cur_text_section->data_allocated) {
|
||||
if (ind1 < 0)
|
||||
tcc_error("program too big");
|
||||
if (ind1 > cur_text_section->data_allocated)
|
||||
section_realloc(cur_text_section, ind1);
|
||||
}
|
||||
cur_text_section->data[ind++] = i&255;
|
||||
i>>=8;
|
||||
cur_text_section->data[ind++] = i&255;
|
||||
|
||||
@ -31,11 +31,8 @@ ST_FUNC void g(int c)
|
||||
if (nocode_wanted)
|
||||
return;
|
||||
ind1 = ind + 1;
|
||||
if ((unsigned)ind1 > cur_text_section->data_allocated) {
|
||||
if (ind1 < 0)
|
||||
tcc_error("program too big");
|
||||
if (ind1 > cur_text_section->data_allocated)
|
||||
section_realloc(cur_text_section, ind1);
|
||||
}
|
||||
cur_text_section->data[ind] = c;
|
||||
ind = ind1;
|
||||
}
|
||||
|
||||
@ -117,11 +117,8 @@ ST_FUNC void o(unsigned int c)
|
||||
int ind1 = ind + 4;
|
||||
if (nocode_wanted)
|
||||
return;
|
||||
if ((unsigned)ind1 > cur_text_section->data_allocated) {
|
||||
if (ind1 < 0)
|
||||
tcc_error("program too big");
|
||||
if (ind1 > cur_text_section->data_allocated)
|
||||
section_realloc(cur_text_section, ind1);
|
||||
}
|
||||
write32le(cur_text_section->data + ind, c);
|
||||
ind = ind1;
|
||||
}
|
||||
|
||||
@ -195,11 +195,8 @@ void C67_g(int c)
|
||||
fprintf(f, " %08X", c);
|
||||
#endif
|
||||
ind1 = ind + 4;
|
||||
if ((unsigned)ind1 > (int) cur_text_section->data_allocated) {
|
||||
if (ind1 < 0)
|
||||
tcc_error("program too big");
|
||||
if (ind1 > (int) cur_text_section->data_allocated)
|
||||
section_realloc(cur_text_section, ind1);
|
||||
}
|
||||
cur_text_section->data[ind] = c & 0xff;
|
||||
cur_text_section->data[ind + 1] = (c >> 8) & 0xff;
|
||||
cur_text_section->data[ind + 2] = (c >> 16) & 0xff;
|
||||
|
||||
2
configure
vendored
2
configure
vendored
@ -230,7 +230,7 @@ Advanced options (experts only):
|
||||
--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-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):
|
||||
--cpu=CPU target CPU [$cpu]
|
||||
|
||||
227
i386-gen.c
227
i386-gen.c
@ -48,7 +48,6 @@ enum {
|
||||
TREG_EBX,
|
||||
TREG_ST0,
|
||||
TREG_ESP = 4,
|
||||
|
||||
TREG_MEM = 0x20
|
||||
};
|
||||
|
||||
@ -90,22 +89,17 @@ ST_DATA const char * const target_machine_defs =
|
||||
"__i386\0"
|
||||
;
|
||||
|
||||
/* define to 1/0 to [not] have EBX as 4th register */
|
||||
#define USE_EBX 0
|
||||
#if defined CONFIG_TCC_PIC
|
||||
#if USE_EBX > 0
|
||||
#error only USE_EBX or GOT_EBX can be set
|
||||
#endif
|
||||
#define GOT_EBX 1
|
||||
# define USE_EBX 2
|
||||
#else
|
||||
#define GOT_EBX 0
|
||||
# define USE_EBX 0 /* define to 1 to have EBX as 4th register */
|
||||
#endif
|
||||
|
||||
ST_DATA const int reg_classes[NB_REGS] = {
|
||||
/* eax */ RC_INT | RC_EAX,
|
||||
/* ecx */ RC_INT | RC_ECX,
|
||||
/* 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,
|
||||
};
|
||||
|
||||
@ -126,11 +120,8 @@ ST_FUNC void g(int c)
|
||||
if (nocode_wanted)
|
||||
return;
|
||||
ind1 = ind + 1;
|
||||
if ((unsigned)ind1 > cur_text_section->data_allocated) {
|
||||
if (ind1 < 0)
|
||||
tcc_error("program too big");
|
||||
if (ind1 > cur_text_section->data_allocated)
|
||||
section_realloc(cur_text_section, ind1);
|
||||
}
|
||||
cur_text_section->data[ind] = c;
|
||||
ind = ind1;
|
||||
}
|
||||
@ -187,33 +178,23 @@ ST_FUNC void gen_fill_nops(int bytes)
|
||||
}
|
||||
|
||||
#if defined CONFIG_TCC_PIC
|
||||
static void gen_static_call(int v);
|
||||
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.cx",
|
||||
"__x86.get_pc_thunk.dx",
|
||||
"__x86.get_pc_thunk.bx"
|
||||
};
|
||||
int pc_thunk;
|
||||
|
||||
if (nocode_wanted)
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
gen_static_call(tok_alloc_const(pc_thunk_name[r]));
|
||||
if (add) {
|
||||
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);
|
||||
r = REG_VALUE(r);
|
||||
if (r == 0)
|
||||
oad(0x05, 1); /* add _GLOBAL_OFFSET_TABLE_, %eax */
|
||||
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
|
||||
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 is_got = (op_reg & TREG_MEM) && !(sym->type.t & VT_STATIC);
|
||||
#endif
|
||||
int op_reg = REG_VALUE(op_r2) << 3;
|
||||
|
||||
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) {
|
||||
/* constant memory reference */
|
||||
#if defined CONFIG_TCC_PIC
|
||||
if (r & VT_SYM) {
|
||||
get_pc_thunk(TREG_EBX, is_got);
|
||||
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);
|
||||
}
|
||||
o(opc);
|
||||
o(0x05 | op_reg);
|
||||
gen_addr32(r, sym, c);
|
||||
} else if ((r & VT_VALMASK) == VT_LOCAL) {
|
||||
o(opc);
|
||||
/* 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 {
|
||||
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 {
|
||||
o(opc);
|
||||
g(0x00 | op_reg | (r & VT_VALMASK));
|
||||
@ -321,14 +293,13 @@ ST_FUNC void load(int r, SValue *sv)
|
||||
fr = sv->r;
|
||||
ft = sv->type.t & ~VT_DEFSIGN;
|
||||
fc = sv->c.i;
|
||||
|
||||
ft &= ~(VT_VOLATILE | VT_CONSTANT);
|
||||
v = fr & VT_VALMASK;
|
||||
|
||||
#ifndef TCC_TARGET_PE
|
||||
#if defined CONFIG_TCC_PIC
|
||||
/* we use indirect access via got */
|
||||
if ((fr & VT_VALMASK) == VT_CONST && (fr & VT_SYM) &&
|
||||
(fr & VT_LVAL) && !(sv->sym->type.t & VT_STATIC)) {
|
||||
if ((fr & (VT_VALMASK|VT_SYM|VT_LVAL)) == (VT_CONST|VT_SYM|VT_LVAL)
|
||||
&& !(sv->sym->type.t & VT_STATIC)) {
|
||||
/* use the result register as a temporal register */
|
||||
int tr = r | TREG_MEM;
|
||||
if (is_float(ft)) {
|
||||
@ -336,14 +307,11 @@ ST_FUNC void load(int r, SValue *sv)
|
||||
tr = get_reg(RC_INT) | TREG_MEM;
|
||||
}
|
||||
gen_modrm(0x8b, tr, fr, sv->sym, 0);
|
||||
|
||||
/* load from the temporal register */
|
||||
fr = tr | VT_LVAL;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
v = fr & VT_VALMASK;
|
||||
if (fr & VT_LVAL) {
|
||||
if (v == VT_LLOCAL) {
|
||||
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);
|
||||
} else {
|
||||
if (v == VT_CONST) {
|
||||
#if defined CONFIG_TCC_PIC
|
||||
if (fr & VT_SYM) {
|
||||
if (sv->sym->type.t & VT_STATIC) {
|
||||
get_pc_thunk(r, 0);
|
||||
o(0x808d | REG_VALUE(r) * 0x900); /* lea $xx(r), r */
|
||||
gen_addrpc32(fr, sv->sym, fc + 6);
|
||||
}
|
||||
else {
|
||||
get_pc_thunk(r, 1);
|
||||
o(0x808b | REG_VALUE(r) * 0x900); /* mov $xx(r), r */
|
||||
gen_gotpcrel(r, sv->sym, fc);
|
||||
}
|
||||
}
|
||||
else
|
||||
if ((fr & (VT_VALMASK|VT_SYM)) == (VT_CONST|VT_SYM)) {
|
||||
if (sv->sym->type.t & VT_STATIC) {
|
||||
get_pc_thunk(r, 0);
|
||||
o(0x808d | REG_VALUE(r) * 0x900); /* lea $xx(r), r */
|
||||
gen_addrpc32(fr, sv->sym, fc + 6);
|
||||
} else {
|
||||
get_pc_thunk(r, 1);
|
||||
o(0x808b | REG_VALUE(r) * 0x900); /* mov $xx(r), r */
|
||||
gen_gotpcrel(r, sv->sym, fc);
|
||||
}
|
||||
} else
|
||||
|
||||
#endif
|
||||
{
|
||||
o(0xb8 + r); /* mov $xx, r */
|
||||
gen_addr32(fr, sv->sym, fc);
|
||||
}
|
||||
if (v == VT_CONST) {
|
||||
o(0xb8 + r); /* mov $xx, r */
|
||||
gen_addr32(fr, sv->sym, fc);
|
||||
} else if (v == VT_LOCAL) {
|
||||
if (fc) {
|
||||
/* lea xxx(%ebp), r */
|
||||
@ -427,27 +392,9 @@ ST_FUNC void load(int r, SValue *sv)
|
||||
/* store register 'r' in lvalue '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;
|
||||
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
|
||||
bt = v->type.t & VT_BTYPE;
|
||||
|
||||
/* XXX: incorrect if float reg to reg */
|
||||
if (bt == VT_FLOAT) {
|
||||
@ -459,26 +406,35 @@ ST_FUNC void store(int r, SValue *v)
|
||||
} else if (bt == VT_LDOUBLE) {
|
||||
opc = 0xdbc0d9; /* fld %st(0), fstpt */
|
||||
r = 7;
|
||||
} else if (bt == VT_SHORT)
|
||||
} else if (bt == VT_SHORT) {
|
||||
opc = 0x8966;
|
||||
else if (bt == VT_BYTE || bt == VT_BOOL)
|
||||
} else if (bt == VT_BYTE || bt == VT_BOOL) {
|
||||
opc = 0x88;
|
||||
else
|
||||
} else {
|
||||
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(3 + (r << 3));
|
||||
}
|
||||
else if (fr == VT_CONST ||
|
||||
fr == VT_LOCAL ||
|
||||
(v->r & VT_LVAL)) {
|
||||
gen_modrm(opc, r, v->r, v->sym, fc);
|
||||
} else
|
||||
#endif
|
||||
|
||||
if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) {
|
||||
gen_modrm(opc, r, v->r, v->sym, fc);
|
||||
} else if (fr != r) {
|
||||
o(opc);
|
||||
o(0xc0 + fr + r * 8); /* mov r, fr */
|
||||
}
|
||||
else
|
||||
tcc_error("store problem");
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Sym *sym;
|
||||
|
||||
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);
|
||||
greloc(cur_text_section, sym, ind - 4, R_386_PC32);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -512,22 +462,18 @@ static void gen_static_call(int v)
|
||||
static void gcall_or_jmp(int is_jmp)
|
||||
{
|
||||
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 */
|
||||
#if defined CONFIG_TCC_PIC
|
||||
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 {
|
||||
if (!(vtop->sym->type.t & VT_STATIC)) {
|
||||
get_pc_thunk(TREG_EBX, 1);
|
||||
oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */
|
||||
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
|
||||
oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */
|
||||
greloc(cur_text_section, vtop->sym, ind - 4, R_386_PC32);
|
||||
} else {
|
||||
/* otherwise, indirect call */
|
||||
r = gv(RC_INT);
|
||||
@ -679,9 +625,9 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||
}
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
#define FUNC_PROLOG_SIZE (10 + USE_EBX)
|
||||
#define FUNC_PROLOG_SIZE (10 + !!USE_EBX)
|
||||
#else
|
||||
#define FUNC_PROLOG_SIZE (9 + (USE_EBX || GOT_EBX))
|
||||
#define FUNC_PROLOG_SIZE (9 + !!USE_EBX)
|
||||
#endif
|
||||
|
||||
/* generate function prolog of type 't' */
|
||||
@ -786,7 +732,6 @@ ST_FUNC void gfunc_epilog(void)
|
||||
#if USE_EBX
|
||||
gen_modrm(0x8b, TREG_EBX, VT_LOCAL, NULL, -(v+4));
|
||||
#endif
|
||||
o(0x5b * GOT_EBX); /* pop ebx */
|
||||
|
||||
o(0xc9); /* leave */
|
||||
if (func_ret_sub == 0) {
|
||||
@ -812,7 +757,9 @@ ST_FUNC void gfunc_epilog(void)
|
||||
o(0x90); /* adjust to FUNC_PROLOG_SIZE */
|
||||
#endif
|
||||
}
|
||||
o(0x53 * (USE_EBX || GOT_EBX)); /* push ebx */
|
||||
#if USE_EBX
|
||||
o(0x53); /* push ebx */
|
||||
#endif
|
||||
ind = saved_ind;
|
||||
}
|
||||
|
||||
|
||||
11
lib/Makefile
11
lib/Makefile
@ -35,7 +35,7 @@ endif
|
||||
|
||||
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)
|
||||
ARM_O = libtcc1.o armeabi.o armflush.o $(COMMON_O)
|
||||
ARM64_O = lib-arm64.o $(COMMON_O)
|
||||
@ -50,15 +50,15 @@ Nat = $(if $X,no,)
|
||||
Cbt = $(Nat)$(subst yes,,$(CONFIG_backtrace))
|
||||
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)WIN_O += bt-dll.o
|
||||
$(Cbc)COMMON_O += bcheck.o
|
||||
|
||||
# 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-osx = $(X86_64_O) $(OSX_O)
|
||||
OBJ-i386-win32 = $(I386_O) chkstk.o $(WIN_O)
|
||||
@ -90,9 +90,6 @@ $(X)%.o : %.c $(TCC)
|
||||
$(X)%.o : %.S $(TCC)
|
||||
$S$(XCC) -c $< -o $@ $(XFLAGS)
|
||||
|
||||
$(TOP)/%.o : %.S $(TCC)
|
||||
$S$(XCC) -c $< -o $@ $(XFLAGS)
|
||||
|
||||
$(TOP)/%.o : %.c $(TCC)
|
||||
$S$(XCC) -c $< -o $@ $(XFLAGS)
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
15
libtcc.c
15
libtcc.c
@ -1899,13 +1899,8 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv)
|
||||
args_parser_add_file(s, r, s->filetype);
|
||||
empty = 0;
|
||||
dorun:
|
||||
if (run) {
|
||||
/* tcc -run <file> <args...> */
|
||||
if (tcc_set_options(s, run) < 0)
|
||||
return -1;
|
||||
x = 0;
|
||||
goto extra_action;
|
||||
}
|
||||
if (run)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
/* Also allow "tcc <files...> -run -- <args...>" */
|
||||
@ -2219,6 +2214,12 @@ unsupported_option:
|
||||
}
|
||||
if (s->link_optind < s->link_argc)
|
||||
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)
|
||||
return 0;
|
||||
if (s->verbose == 2)
|
||||
|
||||
@ -98,11 +98,8 @@ ST_FUNC void g(int c)
|
||||
if (nocode_wanted)
|
||||
return;
|
||||
ind1 = ind + 1;
|
||||
if ((unsigned)ind1 > cur_text_section->data_allocated) {
|
||||
if (ind1 < 0)
|
||||
tcc_error("program too big");
|
||||
if (ind1 > cur_text_section->data_allocated)
|
||||
section_realloc(cur_text_section, ind1);
|
||||
}
|
||||
cur_text_section->data[ind] = c;
|
||||
ind = ind1;
|
||||
}
|
||||
|
||||
@ -115,11 +115,8 @@ ST_FUNC void o(unsigned int c)
|
||||
int ind1 = ind + 4;
|
||||
if (nocode_wanted)
|
||||
return;
|
||||
if ((unsigned)ind1 > cur_text_section->data_allocated) {
|
||||
if (ind1 < 0)
|
||||
tcc_error("program too big");
|
||||
if (ind1 > cur_text_section->data_allocated)
|
||||
section_realloc(cur_text_section, ind1);
|
||||
}
|
||||
write32le(cur_text_section->data + ind, c);
|
||||
ind = ind1;
|
||||
}
|
||||
|
||||
29
tccasm.c
29
tccasm.c
@ -684,17 +684,14 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||
next();
|
||||
asm_expr(s1, &e);
|
||||
n = e.v;
|
||||
if (n != e.v || n < 0)
|
||||
range:
|
||||
tcc_error(".org out of range");
|
||||
esym = elfsym(e.sym);
|
||||
if (esym) {
|
||||
if (esym->st_shndx != cur_text_section->sh_num)
|
||||
expect("constant or same-section symbol");
|
||||
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)
|
||||
tcc_error("attempt to .org backwards");
|
||||
v = 0;
|
||||
@ -719,8 +716,8 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||
do {
|
||||
Sym *sym;
|
||||
next();
|
||||
if (tok < TOK_IDENT || tok >= SYM_FIRST_ANOM)
|
||||
tcc_error("Illegal symbol %s", get_tok_str(tok1, NULL));
|
||||
if (tok < TOK_IDENT)
|
||||
expect("identifier");
|
||||
sym = get_asm_sym(tok, NULL);
|
||||
if (tok1 != TOK_ASMDIR_hidden)
|
||||
sym->type.t &= ~VT_STATIC;
|
||||
@ -816,15 +813,12 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||
{
|
||||
Sym *sym;
|
||||
|
||||
tok1 = tok;
|
||||
next();
|
||||
if (tok < TOK_IDENT || tok >= SYM_FIRST_ANOM)
|
||||
goto nolab;
|
||||
if (tok < TOK_IDENT)
|
||||
expect("identifier");
|
||||
sym = asm_label_find(tok);
|
||||
if (!sym) {
|
||||
nolab:
|
||||
tcc_error("label not found: %s", get_tok_str(tok1, NULL));
|
||||
}
|
||||
if (!sym)
|
||||
tcc_error("label not found: %s", get_tok_str(tok, NULL));
|
||||
/* XXX .size name,label2-label1 */
|
||||
tcc_warning_c(warn_unsupported)("ignoring .size %s,*", get_tok_str(tok, NULL));
|
||||
next();
|
||||
@ -840,10 +834,9 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||
const char *newtype;
|
||||
int st_type;
|
||||
|
||||
tok1 = tok;
|
||||
next();
|
||||
if (tok < TOK_IDENT || tok >= SYM_FIRST_ANOM)
|
||||
tcc_error("Illegal symbol %s", get_tok_str(tok1, NULL));
|
||||
if (tok < TOK_IDENT)
|
||||
expect("identifier");
|
||||
sym = get_asm_sym(tok, NULL);
|
||||
next();
|
||||
skip(',');
|
||||
@ -1192,7 +1185,7 @@ static void subst_asm_operands(ASMOperand *operands, int nb_operands,
|
||||
modifier = *str++;
|
||||
index = find_constraint(operands, nb_operands, str, &str);
|
||||
if (index < 0)
|
||||
error:
|
||||
error:
|
||||
tcc_error("invalid operand reference after %%");
|
||||
op = &operands[index];
|
||||
if (modifier == 'l') {
|
||||
|
||||
6
tccelf.c
6
tccelf.c
@ -1840,9 +1840,6 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
|
||||
tcc_add_dll(s1, TCC_LIBGCC, AFF_PRINT_ERROR);
|
||||
}
|
||||
#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
|
||||
tcc_add_library(s1, "gcc_s"); // unwind code
|
||||
#endif
|
||||
@ -3103,9 +3100,6 @@ LIBTCCAPI int elf_output_obj(TCCState *s1, const char *filename)
|
||||
{
|
||||
Section *s;
|
||||
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 */
|
||||
alloc_sec_names(s1, 1);
|
||||
file_offset = (sizeof (ElfW(Ehdr)) + 3) & -4;
|
||||
|
||||
38
tccgen.c
38
tccgen.c
@ -3589,8 +3589,7 @@ static void cast_error(CType *st, CType *dt)
|
||||
static void verify_assign_cast(CType *dt)
|
||||
{
|
||||
CType *st, *type1, *type2;
|
||||
Sym *sym;
|
||||
int dbt, sbt, qualwarn, lvl, compat;
|
||||
int dbt, sbt, qualwarn, lvl;
|
||||
|
||||
st = &vtop->type; /* source type */
|
||||
dbt = dt->t & VT_BTYPE;
|
||||
@ -3644,29 +3643,8 @@ static void verify_assign_cast(CType *dt)
|
||||
base types, though, in particular for unsigned enums
|
||||
and signed int targets. */
|
||||
} else {
|
||||
compat = 0;
|
||||
/* Don't warn if the source struct (recursively) contains
|
||||
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;
|
||||
}
|
||||
tcc_warning("assignment from incompatible pointer type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (qualwarn)
|
||||
@ -7837,9 +7815,6 @@ static void init_putv(init_params *p, CType *type, unsigned long c)
|
||||
ElfW_Rel *rel;
|
||||
esym = elfsym(vtop->sym);
|
||||
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);
|
||||
if (ssec->reloc) {
|
||||
/* 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 */
|
||||
type = btype;
|
||||
ad = adbase;
|
||||
if (l == VT_CMP) {
|
||||
type_decl(&type, &ad, &v, TYPE_DIRECT | TYPE_PARAM);
|
||||
} else {
|
||||
type_decl(&type, &ad, &v, TYPE_DIRECT);
|
||||
}
|
||||
type_decl(&type, &ad, &v, l == VT_CMP ? TYPE_DIRECT | TYPE_PARAM : TYPE_DIRECT);
|
||||
/*ptype("decl", &type, v);*/
|
||||
|
||||
if ((type.t & VT_BTYPE) == VT_FUNC) {
|
||||
if ((type.t & VT_STATIC) && (l != VT_CONST))
|
||||
tcc_error("function without file scope cannot be static");
|
||||
|
||||
367
tccpp.c
367
tccpp.c
@ -115,89 +115,49 @@ ST_FUNC void expect(const char *msg)
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* 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
|
||||
|
||||
#ifndef USE_TAL
|
||||
#define tal_free(al, p) tcc_free_impl(p)
|
||||
#define tal_realloc(al, p, size) tcc_realloc_impl(p, size)
|
||||
#define tal_new(a,b,c)
|
||||
#ifndef USE_TAL /* may cause memory leaks after errors */
|
||||
#define tal_free(al, p) tcc_free(p)
|
||||
#define tal_realloc(al, p, size) tcc_realloc(p, size)
|
||||
#define tal_new(a,b)
|
||||
#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
|
||||
#if !defined(MEM_DEBUG)
|
||||
#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
|
||||
#else
|
||||
#define TAL_DEBUG MEM_DEBUG
|
||||
//#define TAL_INFO 1 /* collect and dump allocators stats */
|
||||
#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_DEBUG_PARAMS , const char *file, int line
|
||||
#define tal_realloc(al, p, size) tal_realloc_impl(al, p, size, __FILE__, __LINE__)
|
||||
#define TAL_DEBUG_PARAMS , const char *sfile, int sline
|
||||
#endif
|
||||
|
||||
#define TOKSYM_TAL_SIZE (768 * 1024) /* allocator for tiny TokenSym in table_ident */
|
||||
#define TOKSTR_TAL_SIZE (768 * 1024) /* allocator for tiny TokenString instances */
|
||||
#define TOKSYM_TAL_LIMIT 256 /* prefer unique limits to distinguish allocators debug msgs */
|
||||
#define TOKSTR_TAL_LIMIT 1024 /* 256 * sizeof(int) */
|
||||
#define TOKSYM_TAL_SIZE (256 * 1024) /* allocator for TokenSym in table_ident */
|
||||
#define TOKSTR_TAL_SIZE (256 * 1024) /* allocator for TokenString instances */
|
||||
|
||||
typedef struct TinyAlloc {
|
||||
unsigned limit;
|
||||
unsigned size;
|
||||
uint8_t *buffer;
|
||||
uint8_t *p;
|
||||
unsigned nb_allocs;
|
||||
struct TinyAlloc *next, *top;
|
||||
#ifdef TAL_INFO
|
||||
unsigned nb_peak;
|
||||
unsigned nb_total;
|
||||
unsigned nb_missed;
|
||||
uint8_t *bufend;
|
||||
struct TinyAlloc *next;
|
||||
unsigned nb_allocs;
|
||||
unsigned size;
|
||||
#if TAL_INFO
|
||||
unsigned nb_peak;
|
||||
unsigned nb_total;
|
||||
uint8_t *peak_p;
|
||||
#endif
|
||||
union {
|
||||
uint8_t buffer[1];
|
||||
size_t _aligner_;
|
||||
};
|
||||
} TinyAlloc;
|
||||
|
||||
typedef struct tal_header_t {
|
||||
size_t size; /* word align */
|
||||
#ifdef TAL_DEBUG
|
||||
#if TAL_DEBUG
|
||||
int line_num; /* negative line_num used for double free check */
|
||||
char file_name[40];
|
||||
#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));
|
||||
al->p = al->buffer = tcc_malloc(size);
|
||||
al->limit = limit;
|
||||
al->size = size;
|
||||
if (pal) *pal = al;
|
||||
TinyAlloc *al = tcc_malloc(sizeof(TinyAlloc) - sizeof (size_t) + size);
|
||||
al->p = al->buffer;
|
||||
al->bufend = al->buffer + size;
|
||||
al->nb_allocs = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
static void tal_delete(TinyAlloc *al)
|
||||
static void tal_delete(TinyAlloc **pal)
|
||||
{
|
||||
TinyAlloc *next;
|
||||
TinyAlloc *al = *pal, *next;
|
||||
|
||||
tail_call:
|
||||
if (!al)
|
||||
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);
|
||||
#if TAL_INFO
|
||||
fprintf(stderr, "tal_delete (&tok%s_alloc):\n", pal == &toksym_alloc ? "sym" : "str");
|
||||
#endif
|
||||
tail_call:
|
||||
#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) {
|
||||
uint8_t *p;
|
||||
fprintf(stderr, "TAL_DEBUG: memory leak %d chunk(s) (limit= %d)\n",
|
||||
al->nb_allocs, al->limit);
|
||||
fprintf(stderr, "TAL_DEBUG: memory leak %d chunk(s)\n", al->nb_allocs);
|
||||
p = al->buffer;
|
||||
while (p < al->p) {
|
||||
tal_header_t *header = (tal_header_t *)p;
|
||||
@ -250,40 +216,45 @@ tail_call:
|
||||
}
|
||||
#endif
|
||||
next = al->next;
|
||||
tcc_free(al->buffer);
|
||||
tcc_free(al);
|
||||
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)
|
||||
return;
|
||||
tail_call:
|
||||
if (al->buffer <= (uint8_t *)p && (uint8_t *)p < al->buffer + al->size) {
|
||||
#ifdef TAL_DEBUG
|
||||
tal_header_t *header = (((tal_header_t *)p) - 1);
|
||||
if (header->line_num < 0) {
|
||||
fprintf(stderr, "%s:%d: TAL_DEBUG: double frees chunk from\n",
|
||||
file, line);
|
||||
fprintf(stderr, "%s:%d: %d bytes\n",
|
||||
header->file_name, (int)-header->line_num, (int)header->size);
|
||||
} else
|
||||
header->line_num = -header->line_num;
|
||||
header = (tal_header_t *)p - 1;
|
||||
#if TAL_DEBUG
|
||||
if (header->line_num < 0) {
|
||||
fprintf(stderr, "%s:%d: TAL_DEBUG: double frees chunk from\n",
|
||||
sfile, sline);
|
||||
fprintf(stderr, "%s:%d: %d bytes\n",
|
||||
header->file_name, (int)-header->line_num, (int)header->size);
|
||||
} else
|
||||
header->line_num = -header->line_num;
|
||||
#endif
|
||||
al->nb_allocs--;
|
||||
if (!al->nb_allocs)
|
||||
al = *pal;
|
||||
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;
|
||||
} else if (al->next) {
|
||||
al = al->next;
|
||||
goto tail_call;
|
||||
}
|
||||
else {
|
||||
pp_alloc_t *alloc = ((pp_alloc_t *)p) - 1;
|
||||
|
||||
PP_ALLOC_REMOVE(alloc);
|
||||
tcc_free(alloc);
|
||||
al->next = *top, *top = al;
|
||||
}
|
||||
} else if ((uint8_t*)p + header->size == al->p) {
|
||||
al->p = (uint8_t*)header;
|
||||
}
|
||||
}
|
||||
|
||||
@ -291,112 +262,66 @@ static void *tal_realloc_impl(TinyAlloc **pal, void *p, unsigned size TAL_DEBUG_
|
||||
{
|
||||
tal_header_t *header;
|
||||
void *ret;
|
||||
int is_own;
|
||||
unsigned adj_size = TAL_ALIGN(size);
|
||||
unsigned adj_size = TAL_ALIGN(size) + sizeof(tal_header_t);
|
||||
TinyAlloc *al = *pal;
|
||||
|
||||
tail_call:
|
||||
is_own = (al->buffer <= (uint8_t *)p && (uint8_t *)p < al->buffer + al->size);
|
||||
if ((!p || is_own) && size <= al->limit) {
|
||||
if (al->p - al->buffer + adj_size + sizeof(tal_header_t) < al->size) {
|
||||
header = (tal_header_t *)al->p;
|
||||
header->size = adj_size;
|
||||
#ifdef TAL_DEBUG
|
||||
{ int ofs = strlen(file) + 1 - sizeof header->file_name;
|
||||
strcpy(header->file_name, file + (ofs > 0 ? ofs : 0));
|
||||
header->line_num = line; }
|
||||
#endif
|
||||
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
|
||||
if (p) {
|
||||
/* reallpc case */
|
||||
while ((uint8_t*)p < al->buffer || (uint8_t*)p > al->bufend)
|
||||
al = al->next;
|
||||
header = (tal_header_t *)p - 1;
|
||||
if ((uint8_t*)p + header->size == al->p)
|
||||
al->p = (uint8_t*)header; /* maybe reuse */
|
||||
if (al->p + adj_size > al->bufend) {
|
||||
ret = tal_realloc(pal, 0, size);
|
||||
memcpy(ret, p, header->size);
|
||||
tal_free(pal, p);
|
||||
return ret;
|
||||
} else if (is_own) {
|
||||
al->nb_allocs--;
|
||||
ret = tal_realloc(*pal, 0, size);
|
||||
header = (((tal_header_t *)p) - 1);
|
||||
if (p) memcpy(ret, p, header->size);
|
||||
#ifdef TAL_DEBUG
|
||||
} else if (al->p != (uint8_t*)header) {
|
||||
memcpy((tal_header_t*)al->p + 1, p, header->size);
|
||||
#if TAL_DEBUG
|
||||
header->line_num = -header->line_num;
|
||||
#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 {
|
||||
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);
|
||||
ret = alloc + 1;
|
||||
}
|
||||
else {
|
||||
tcc_free(alloc);
|
||||
ret = NULL;
|
||||
}
|
||||
/* new alloc case */
|
||||
while (al->p + adj_size > al->bufend) {
|
||||
al = al->next;
|
||||
if (!al) {
|
||||
unsigned new_size = (*pal)->size;
|
||||
if (adj_size > new_size) {
|
||||
new_size = adj_size;
|
||||
//fprintf(stderr, "%s:%d: alloc big tal: %u\n", file->filename, file->line_num, adj_size - sizeof(tal_header_t));
|
||||
}
|
||||
al = tal_new(pal, new_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
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
|
||||
return ret;
|
||||
}
|
||||
|
||||
#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 */
|
||||
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;
|
||||
}
|
||||
|
||||
ts = tal_realloc(toksym_alloc, 0, sizeof(TokenSym) + len);
|
||||
ts = tal_realloc(&toksym_alloc, 0, sizeof(TokenSym) + len);
|
||||
table_ident[i] = ts;
|
||||
ts->tok = tok_ident++;
|
||||
ts->sym_define = NULL;
|
||||
@ -1084,20 +1009,20 @@ ST_INLN void tok_str_new(TokenString *s)
|
||||
|
||||
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);
|
||||
return 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)
|
||||
{
|
||||
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)
|
||||
@ -1110,7 +1035,7 @@ ST_FUNC int *tok_str_realloc(TokenString *s, int new_size)
|
||||
while (size < new_size)
|
||||
size = size * 2;
|
||||
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->str = str;
|
||||
}
|
||||
@ -2550,7 +2475,7 @@ static void parse_number(const char *p)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unsigned long long n = 0, n1 = 0;
|
||||
unsigned long long n, n1;
|
||||
int lcount, ucount, ov = 0;
|
||||
const char *p1;
|
||||
|
||||
@ -2561,6 +2486,7 @@ static void parse_number(const char *p)
|
||||
b = 8;
|
||||
q++;
|
||||
}
|
||||
n = 0;
|
||||
while(1) {
|
||||
t = *q++;
|
||||
/* no need for checks except for base 10 / 8 errors */
|
||||
@ -2574,23 +2500,13 @@ static void parse_number(const char *p)
|
||||
t = t - '0';
|
||||
if (t >= b)
|
||||
tcc_error("invalid digit");
|
||||
n1 = n;
|
||||
n = n * b + t;
|
||||
if (!ov) {
|
||||
/* detect overflow */
|
||||
if (n1 >= 0x1000000000000000ULL && n / b != n1)
|
||||
ov = 1;
|
||||
else
|
||||
n1 = n;
|
||||
}
|
||||
/* detect overflow */
|
||||
if (n1 >= 0x1000000000000000ULL && n / b != n1)
|
||||
ov = 1;
|
||||
}
|
||||
#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
|
||||
the constant must have according to the constant suffix(es) */
|
||||
lcount = ucount = 0;
|
||||
@ -3830,9 +3746,8 @@ ST_FUNC void tccpp_new(TCCState *s)
|
||||
set_idnum(i, IS_ID);
|
||||
|
||||
/* init allocators */
|
||||
tal_new(&toksym_alloc, TOKSYM_TAL_LIMIT, TOKSYM_TAL_SIZE);
|
||||
tal_new(&tokstr_alloc, TOKSTR_TAL_LIMIT, TOKSTR_TAL_SIZE);
|
||||
tal_alloc_init();
|
||||
tal_new(&toksym_alloc, TOKSYM_TAL_SIZE);
|
||||
tal_new(&tokstr_alloc, TOKSTR_TAL_SIZE);
|
||||
|
||||
memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
|
||||
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(&cstr_buf);
|
||||
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_realloc(&tokstr_buf, TOKSTR_MAX_SIZE);
|
||||
tok_str_new(&unget_buf);
|
||||
|
||||
tok_ident = TOK_IDENT;
|
||||
p = tcc_keywords;
|
||||
@ -3876,8 +3792,8 @@ ST_FUNC void tccpp_delete(TCCState *s)
|
||||
n = tok_ident - TOK_IDENT;
|
||||
if (n > total_idents)
|
||||
total_idents = n;
|
||||
for(i = 0; i < n; i++)
|
||||
tal_free(toksym_alloc, table_ident[i]);
|
||||
for (i = n; --i >= 0;)
|
||||
tal_free(&toksym_alloc, table_ident[i]);
|
||||
tcc_free(table_ident);
|
||||
table_ident = NULL;
|
||||
|
||||
@ -3888,11 +3804,8 @@ ST_FUNC void tccpp_delete(TCCState *s)
|
||||
tok_str_free_str(unget_buf.str);
|
||||
|
||||
/* free allocators */
|
||||
tal_alloc_free();
|
||||
tal_delete(toksym_alloc);
|
||||
toksym_alloc = NULL;
|
||||
tal_delete(tokstr_alloc);
|
||||
tokstr_alloc = NULL;
|
||||
tal_delete(&toksym_alloc);
|
||||
tal_delete(&tokstr_alloc);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
33
tccrun.c
33
tccrun.c
@ -120,10 +120,7 @@ static int rt_mem(TCCState *s1, int size)
|
||||
unlink(tmpfname);
|
||||
ftruncate(fd, size);
|
||||
|
||||
ptr = mmap(NULL, size * 2, PROT_READ|PROT_EXEC|(s1->do_debug ? PROT_WRITE : 0), 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);
|
||||
ptr = mmap(NULL, size * 2, PROT_READ|PROT_EXEC, MAP_SHARED, fd, 0);
|
||||
/* mmap RW memory at fixed distance */
|
||||
prw = mmap((char*)ptr + size, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, 0);
|
||||
close(fd);
|
||||
@ -224,14 +221,11 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||
return 0;
|
||||
|
||||
tcc_add_symbol(s1, "__rt_exit", rt_exit);
|
||||
if (s1->nostdlib) {
|
||||
tcc_add_support(s1, "run_nostdlib.o");
|
||||
s1->run_main = top_sym = s1->elf_entryname ? s1->elf_entryname : "_start";
|
||||
} else {
|
||||
tcc_add_support(s1, "runmain.o");
|
||||
s1->run_main = "_runmain";
|
||||
top_sym = "main";
|
||||
}
|
||||
s1->run_main = "_runmain", top_sym = "main";
|
||||
if (s1->elf_entryname)
|
||||
s1->run_main = top_sym = s1->elf_entryname;
|
||||
tcc_add_support(s1, "runmain.o");
|
||||
|
||||
if (tcc_relocate(s1) < 0)
|
||||
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));
|
||||
if (0 == ret) {
|
||||
if (s1->nostdlib) {
|
||||
void (*run_nostdlib)(void *start, int argc, char **argv, char **envp);
|
||||
|
||||
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 = prog_main(argc, argv, envp);
|
||||
} else if (RT_EXIT_ZERO == ret) {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (s1->dflag & 16 && ret) /* tcc -dt -run ... */
|
||||
fprintf(s1->ppfp, "[returns %d]\n", ret), fflush(s1->ppfp);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -262,45 +262,3 @@ bar 15 12 34
|
||||
[test_scope_3]
|
||||
60_errors_and_warnings.c:548: warning: assignment from incompatible pointer 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
|
||||
|
||||
@ -175,11 +175,8 @@ ST_FUNC void g(int c)
|
||||
if (nocode_wanted)
|
||||
return;
|
||||
ind1 = ind + 1;
|
||||
if ((unsigned)ind1 > cur_text_section->data_allocated) {
|
||||
if (ind1 < 0)
|
||||
tcc_error("program too big");
|
||||
if (ind1 > cur_text_section->data_allocated)
|
||||
section_realloc(cur_text_section, ind1);
|
||||
}
|
||||
cur_text_section->data[ind] = c;
|
||||
ind = ind1;
|
||||
}
|
||||
|
||||
@ -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++;
|
||||
}
|
||||
/* ignore relocation check for stab section */
|
||||
if ((stab_section == NULL ||
|
||||
addr < stab_section->sh_addr ||
|
||||
addr >= (stab_section->sh_addr + stab_section->data_offset)) &&
|
||||
((type == R_X86_64_32 &&
|
||||
(unsigned long long)val > 4294967295ULL) ||
|
||||
(type == R_X86_64_32S &&
|
||||
((long long)val < -2147483648LL || (long long)val > 2147483647LL))))
|
||||
tcc_error_noabort("internal error: relocation %d failed", type);
|
||||
if ((type == R_X86_64_32 ? val != (unsigned)val : val != (int)val)
|
||||
/* ignore relocation check for stab section */
|
||||
&& (stab_section == NULL ||
|
||||
addr < stab_section->sh_addr ||
|
||||
addr >= (stab_section->sh_addr + stab_section->data_offset))) {
|
||||
tcc_error_noabort("relocation 'R_X86_64_32[S]' out of range");
|
||||
}
|
||||
add32le(ptr, val);
|
||||
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 */
|
||||
if (((ElfW(Sym)*)symtab_section->data)[sym_index].st_shndx != SHN_UNDEF)
|
||||
#endif
|
||||
tcc_error_noabort("internal error: relocation %d failed", type);
|
||||
tcc_error_noabort("relocation '%d' out of range", type);
|
||||
}
|
||||
add32le(ptr, diff);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user