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
|
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
|
||||||
|
|||||||
14
Makefile
14
Makefile
@ -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"
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
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-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]
|
||||||
|
|||||||
227
i386-gen.c
227
i386-gen.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
11
lib/Makefile
11
lib/Makefile
@ -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)
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
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)
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
29
tccasm.c
29
tccasm.c
@ -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') {
|
||||||
|
|||||||
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);
|
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;
|
||||||
|
|||||||
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)
|
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
367
tccpp.c
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|||||||
33
tccrun.c
33
tccrun.c
@ -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);
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user