I'm sorry for this delayed response. I've been camping, no wifi for a minute...
On Mon, Mar 4, 2024 at 3:47 AM grischka via Tinycc-devel < tinycc-devel@nongnu.org> wrote: > On 03.03.2024 21:26, Eric Raible wrote: > > > isn't there a garbage collecting done at the end to remove all the > unused stuff > > > to produce a binary that contains only the necessary parts ? > > > > That very well might be the case, but given that tcc_get_symbol() > > can be used at any time between tcc_relocate() and tcc_delete(), > > it follows that _at least_ symbols are resident in the TCCState. > > What I'm wondering about is the feasibility of keeping just code and > > data, and flushing everything else. This would require a new API - > > something like tcc_finalize(TCCState *) or perhaps > > tcc_finalize(TCCState *, flags), where flags specify what to flush. > > Me thinks this discussion is going around in circles. > I'm sorry for that. tcc as it has been has been tremendously useful to me, and all I'm trying to do is help. Btw, I was not advocating for any changes to tcc_relocate() except that once it became a 1-arg function I suggested that it could be eliminated and tcc_add_symbol() could call it on demand. Your tcc_finalize() subject of obsession was what we already had > all the time since 0.9.25, that is the option to allocate the > executable code separately from the state and therefor the option > to delete (finalize) the state and still keep the code. > I understand that now. I had previously used only automatic allocation in tcc_relocate(), and since it worked I never explored further. My main interest was for tcc_set_realloc(), and I am happy that it was "approved". ... > At which point I found that maintaining two options for running > code might not be to the best for both sides, neither for tcc wrt. > maintainability nor for users wrt. avoidance of inconvenience. > ... > Where simple plus complicated is more complicated than just > complicated btw. > > I understand the frustration and agree that maintainability is a crucial consideration. > > I don't know enough about the internals, but if I'm willing to run with > > CONFIG_RUNMEM_RO, it seems like the per TCCState memory use in my case > > could be decreased from something like 29K to 1K or 2K. > > > > I should mention that the memory usage in my case is 29K regardless > > of whether CONFIG_RUNMEM_RO is 0 or 1. > > How do you know this? > B.c I installed a custom allocator with tcc_set_realloc(). My exact case is hard to reproduce except for me, but the following standalone example illustrates that mem_cur_size might be incorrect: #if 0Everything here assumes the following patch:diff --git a/libtcc.c b/libtcc.cindex 6d720e74..332ec13d 100644--- a/libtcc.c+++ b/libtcc.c@@ -844,6 +844,12 @@ LIBTCCAPI TCCState *tcc_new(void) LIBTCCAPI void tcc_delete(TCCState *s1) {+ if (s1->do_bench) {+ fprintf(stderr, "Top of tcc_delete()\n");+ tcc_print_stats(s1, 0);+ fprintf(stderr, "Early return from tcc_delete() - expect leaks!\n");+ return;+ } /* free sections */ tccelf_delete(s1); @@ -2209,5 +2215,6 @@ PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time) } #endif fprintf(stderr, " %d max (bytes)\n", mem_max_size);+ fprintf(stderr, "mem_cur_size=%d (bytes)\n", mem_cur_size); #endif } Running this program under valgrind on my arm debian with either theseconfigs seems to show that mem_max_size is undercounting../configure --extra-cflags="-DMEM_DEBUG"./configure --extra-cflags="-DMEM_DEBUG -DCONFIG_RUNMEM_RO=0"#endif#include <stdio.h>#include <stdlib.h>#include <malloc.h>#include "libtcc.h"typedef struct block { unsigned long size; char data[];} block;#define _B2S(block) ((block) ? (block)->size : 0)#define _B2D(block) ((block) ? (block)->data : 0)#define _D2B(data) ((data) ? (block *)(data) - 1 : 0)#define _D2S(data) _B2S(_D2B(data))static unsigned int blocks, mcalls, rcalls, fcalls, bytes, max;static void *reallocator(void *data, unsigned long want){ block *b = _D2B(data); int had = _D2S(data); if (want) { // some accounting if (had) { ++rcalls; bytes -= had + sizeof b; } else { ++blocks; ++mcalls; } bytes += want + sizeof b; if (max < bytes) max = bytes; b = realloc(b, want + sizeof b); b->size = want; } else if (had) { --blocks; ++fcalls; bytes -= had + sizeof b; free(b); b = 0; } return _B2D(b);}static void fatal(char *msg){ fprintf(stderr, "%s\n", msg); exit(1);}int main(){ tcc_set_realloc(reallocator); TCCState *state = tcc_new(); if (!state) fatal("excuse me"); tcc_set_options(state, "-bench"); tcc_set_output_type(state, TCC_OUTPUT_MEMORY); if (tcc_compile_string(state, "int x, y, z=1;\n" "int foo(int arg) { return arg + z; }")) fatal("sorry"); if (tcc_relocate(state)) fatal("so sorry"); int (*foo)(int) = tcc_get_symbol(state, "foo"); if (!foo || foo(41) != 42) fatal("I am truly sorry"); printf("Custom 1: %d bytes, %d max, mcalls %d, rcalls %d, fcalls %d, blocks %d\n", bytes, max, mcalls, rcalls, fcalls, blocks); tcc_delete(state); // This one is only useful if the above patch is NOT applied printf("Custom 2: %d bytes, %d max, mcalls %d, rcalls %d, fcalls %d, blocks %d\n", bytes, max, mcalls, rcalls, fcalls, blocks); return 0;} That's it for now, sorry for the long message. - Eric
_______________________________________________ Tinycc-devel mailing list Tinycc-devel@nongnu.org https://lists.nongnu.org/mailman/listinfo/tinycc-devel