Hi there,

I've made the patch in my local branch and the tests. Hope it's usefull.

Following are the test commands you may use.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_tmain:
----------------------------------------------------
tcc.exe test_tmain.c -D_UNICODE &&test_tmain
tcc.exe test_tmain.c &&test_tmain

tcc.exe test_tmain.c -D_UNICODE -run
tcc.exe test_tmain.c -run
----------------------------------------------------


_tWinMain:
-----------------------------------------------------------------------
-D_UNICODE for _tWinMain -*-> wWinMain

-DUNICODE for LPTSTR --> TCHAR -*-> WCHAR --> wchar_t
ASCI: LPTSTR --> TCHAR ---> CHAR  --> char

LPWSTR --> WCHAR --> wchar_t
LPSTR --> CHAR --> char
..........................................................................................................
tcc.exe test_tWinMain.c -D_UNICODE -DUNICODE -luser32 && test_tWinMain "Show me!"
tcc.exe test_tWinMain.c -luser32 && test_tWinMain "Show me!"

tcc.exe test_tWinMain.c -D_UNICODE -DUNICODE -luser32 -run
tcc.exe test_tWinMain.c -luser32 -run
-----------------------------------------------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Also, my analysis notes file is attached. It could be a little different as it is generated from my issue branch.

And as in the last section, the referred "spliting of the crt files", do you have any interest? Do you have any other ideas?

Regards,
YX Hao

Attachment: commit-28b6740
Description: Binary data

***********************************************
For _tmain:

findstr /s /n /r /c:"[^a-zA-Z][w]*main[^a-zA-Z]" *.c

-----------------------------------------------
arm-gen.c:902:   See the comment for the main loop in copy_params() for the 
reason. */

-----------------------------------------------
conftest.c:44:int main(int argc, char *argv[])

-----------------------------------------------
il-gen.c:434:    if (!strcmp(funcname, "main"))
   if (!strcmp(funcname, "main"))
       fprintf(il_outfile, " .entrypoint\n");

??? who/where/which platform uses this?

-----------------------------------------------
lib\bcheck.c:421:void __bound_main_arg(void **p)

-----------------------------------------------
libtcc.c:1047:    s->runtime_main = "main";

for tcc_new() ... add a flag "unicode_mode"
......
tcc.h
..............................................
#ifdef TCC_TARGET_PE
   /* PE info */
   int pe_subsystem;
   unsigned pe_file_align;
   unsigned pe_stack_size;
# ifdef TCC_TARGET_X86_64
   Section *uw_pdata;
   int uw_sym;
   unsigned uw_offs;
# endif
   int unicode_mode; /* _tmain, _tWinMain */
#endif
..............................................
#ifdef TCC_IS_NATIVE
   s->runtime_main = "main";
#endif
#ifdef TCC_TARGET_PE
   s->unicode_mode = 0;
#endif
   return s;
..............................................

-----------------------------------------------
tcc.c:244:int main(int argc, char **argv)

-----------------------------------------------
*** not for TCC_TARGET_COFF
tcccoff.c:46:int C67_main_entry_point;
tcccoff.c:108:    o_filehdr.entrypt = C67_main_entry_point;     /* entry pt.    
                      */
tcccoff.c:931:      // strip off any leading underscore (except for other main 
routine)

-----------------------------------------------
tcccoff.c:933:      if (name[0] == '_' && strcmp(name, "_main") != 0)
?
ST_FUNC int tcc_load_coff(TCCState * s1, int fd)
{
xxx-unknown
..............................................
            // strip off any leading underscore (except for other main routine)

            if (name[0] == '_'
           && (strcmp(name, s1->unicode_mode == 0 ? "_main" : "_wmain") != 0))
                name++;

           /* skip unused (undefined) */ /* Need or not? */
           if ((s1->unicode_mode == 0 && strcmp(name, "wmain") != 0)
               || (s1->unicode_mode && strcmp(name, "main") != 0))
            tcc_add_symbol(s1, name, (void*)(uintptr_t)csym.n_value);
        }
..............................................
tcc_add_symbol [---> (TCC_TARGET_PE) pe_putimport] --->| add_elf_sym

-----------------------------------------------
tccgen.c:5827:        && !strcmp(get_tok_str(sym->v, NULL), "main")) {
??? compilation stage
..............................................
#ifdef CONFIG_TCC_BCHECK
   if (tcc_state->do_bounds_check
       && (!strcmp(get_tok_str(sym->v, NULL),
#ifdef TCC_TARGET_PE
       tcc_state->unicode_entry == 3 /*PE_EXE*/ ? "wmain" :
       //tcc_state->unicode_entry == 2 /*PE_GUI*/ ? PE_STDSYM("wWinMain","@16") 
:
       //tcc_state->pe_subsystem == 2 /*PE_GUI*/ ? PE_STDSYM("WinMain","@16") :
#endif
       "main"))) {
       int i;

       sym = local_stack;
       for (i = 0, sym = local_stack; i < 2; i++, sym = sym->prev) {
           if (sym->v & SYM_FIELD || sym->prev->v & SYM_FIELD)
               break;
           vpush_global_sym(&func_old_type, TOK___bound_main_arg);
           vset(&sym->type, sym->r, sym->c);
           gfunc_call(1);
       }
   }
#endif
..............................................

-----------------------------------------------
tccgen.c:5834:            vpush_global_sym(&func_old_type, 
TOK___bound_main_arg);

-----------------------------------------------
tccpe.c:1759:        ? PE_GUI == pe_type ? "__runwinmain" : wconsole == 0 ? "_main" : 
"_wmain"
tccpe.c:1793:        s1->runtime_main = start_symbol;
static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
{
..............................................
   else {
       pe_type = PE_EXE;
       if (find_elf_sym(symtab_section, "wmain"))
           s1->unicode_mode = 1;
   }
..............................................
   if (TCC_OUTPUT_MEMORY == s1->output_type) {
       pe_type = PE_RUN;
#ifdef TCC_IS_NATIVE
       s1->runtime_main = start_symbol;
#endif
   } else {
       pe->start_addr = (DWORD)(uintptr_t)tcc_get_symbol_err(s1, start_symbol);
   }
..............................................
   start_symbol =
       TCC_OUTPUT_MEMORY == s1->output_type
       ? PE_GUI == pe_type ? "__runwinmain" : s1->unicode_mode ? "_wmain" : 
"_main"
       : PE_DLL == pe_type ? PE_STDSYM("__dllstart","@12")
       : PE_GUI == pe_type ? "__winstart" : s1->unicode_mode ? "__wstart" : 
"__start"
       ;
..............................................
(tccpe.c) pe_add_runtime --->
(libtcc.c) tcc_add_library ---> tcc_add_library_internal ---> 
tcc_add_file_internal --->
(tccelf.c) [tcc_load_archive --->] tcc_load_object_file --->| add_elf_sym

++ tccelf.c
..............................................
#ifdef TCC_TARGET_PE
#ifdef TCC_TARGET_X86_64
#define PE_STDSYM(n,s) n
#else
#define PE_STDSYM(n,s) "_" n s
#endif
#endif
..............................................
ST_FUNC int tcc_load_object_file(TCCState *s1,
                               int fd, unsigned long file_offset)
{
..............................................
       /* add symbol */
       name = (char *) strtab + sym->st_name;
#ifdef TCC_TARGET_PE
       /* skip unused (undefined) */
       int unicode_mode = s1->unicode_mode;
       if ((unicode_mode && strcmp(name, "main") != 0)
           || (unicode_mode == 0 && strcmp(name, "wmain") != 0))
#endif
       sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
                               sym->st_info, sym->st_other,
                               sym->st_shndx, name);
       old_to_new_syms[i] = sym_index;
..............................................

-----------------------------------------------
tccrun.c:29:ST_DATA void *rt_prog_main;
tccrun.c:94:    int (*prog_main)(int, char **);
tccrun.c:100:    prog_main = tcc_get_symbol_err(s1, s1->runtime_main);

-----------------------------------------------
tccrun.c:105:        rt_prog_main = prog_main;
tccrun.c:130:        ret = (*prog_main)(argc, argv);
tccrun.c:140:        ret = (*prog_main)(argc, argv);
tccrun.c:406:        if (pc == (addr_t)rt_prog_main && pc)

-----------------------------------------------
win32\lib\crt1.c:19:int main(int argc, char **argv, char **env);
win32\lib\crt1.c:33:        ret = main(argc, argv, env);
+++
For ExitProcess, Add "#include <windows.h>".

===============================================
"add_elf_sym" is used in many other cases!
So, the skipping judgement placed out of it and only for win.
===============================================

-----------------------------------------------
win32\tools\tiny_impdef.c:47:int main(int argc, char **argv)
win32\tools\tiny_libmaker.c:74:int main(int argc, char **argv)

examples\ex1.c:4:int main()
examples\ex2.c:67:int main(int argc, char **argv)
examples\ex3.c:12:int main(int argc, char **argv)
examples\ex4.c:8:int main(int argc, char **argv)
examples\ex5.c:4:int main()

tests\abitest.c:422:int main(int argc, char **argv) {
tests\boundtest.c:208:int main(int argc, char **argv)
tests\libtcc_test.c:35:int main(int argc, char **argv)
tests\tcctest.c:636:int main(int argc, char **argv)
tests\tests2\00_assignment.c:3:int main() tests\tests2\01_comment.c:3:int main() tests\tests2\02_printf.c:3:int main() tests\tests2\03_struct.c:9:int main() tests\tests2\04_for.c:3:int main() tests\tests2\05_array.c:3:int main() tests\tests2\06_case.c:3:int main()
tests\tests2\07_function.c:18:int main()
tests\tests2\08_while.c:3:int main()
tests\tests2\09_do_while.c:3:int main()
tests\tests2\10_pointer.c:10:int main()
tests\tests2\11_precedence.c:3:int main()
tests\tests2\12_hashdefine.c:6:int main()
tests\tests2\13_integer_literals.c:3:int main()
tests\tests2\14_if.c:3:int main()
tests\tests2\15_recursion.c:11:int main()
tests\tests2\16_nesting.c:3:int main()
tests\tests2\17_enum.c:15:int main()
tests\tests2\18_include.c:3:int main()
tests\tests2\19_pointer_arithmetic.c:3:int main()
tests\tests2\20_pointer_comparison.c:3:int main()
tests\tests2\21_char_array.c:3:int main()
tests\tests2\22_floating_point.c:4:int main()
tests\tests2\23_type_coercion.c:18:int main()
tests\tests2\24_math_library.c:4:int main()
tests\tests2\25_quicksort.c:47:int main()
tests\tests2\26_character_constants.c:3:int main()
tests\tests2\27_sizeof.c:3:int main()
tests\tests2\28_strings.c:5:int main()
tests\tests2\29_array_address.c:4:int main()
tests\tests2\30_hanoi.c:100:int main()
tests\tests2\31_args.c:3:int main(int argc, char **argv)
tests\tests2\32_led.c:224:int main()
tests\tests2\32_led.c:234:int main(int argc, char **argv)
tests\tests2\33_ternary_op.c:3:int main()
tests\tests2\34_array_assignment.c:3:int main()
tests\tests2\35_sizeof.c:3:int main()
tests\tests2\36_array_initialisers.c:3:int main()
tests\tests2\37_sprintf.c:3:int main()
tests\tests2\38_multiple_array_index.c:3:int main()
tests\tests2\39_typedef.c:15:int main()
tests\tests2\40_stdio.c:3:int main()
tests\tests2\41_hashif.c:3:int main()
tests\tests2\42_function_pointer.c:11:int main()
tests\tests2\43_void_param.c:8:int main()
tests\tests2\44_scoped_declarations.c:3:int main()
tests\tests2\45_empty_for.c:3:int main()
tests\tests2\46_grep.c:481:int main(int argc, char **argv)
tests\tests2\47_switch_return.c:15:int main()
tests\tests2\48_nested_break.c:3:int main()
tests\tests2\49_bracket_evaluation.c:11:int main()
tests\tests2\50_logical_second_arg.c:15:int main()
tests\tests2\51_static.c:14:int main()
tests\tests2\52_unnamed_enum.c:5:int main()
tests\tests2\54_goto.c:47:int main()
tests\tests2\55_lshift_type.c:45:int main (int argc, char **argv)
tests\tests2\63_local_enumerator_redefinition.c:6:int main(void)
tests\tests2\64_macro_nesting.c:5:int main(void)
tests\tests2\67_macro_concat.c:6:int main(void)
tests\tests2\68_macro_param_list_err_1.c:4:int main(void)
tests\tests2\69_macro_param_list_err_2.c:4:int main(void)
tests\vla_test.c:75:int main(int argc, char **argv) {

win32\examples\fib.c:11:int main(int argc, char **argv) win32\examples\hello_dll.c:3:// HELLO_DLL.C - Windows DLL example - main application part
win32\examples\hello_win.c:95:    // the main window.
win32\examples\libtcc_test.c:35:int main(int argc, char **argv)

+++++++++++++++++++++++++++++++++++++++++++++++
***********************************************
For _tWinMain:
findstr /s /n /r /c:"winstart" *.c

-----------------------------------------------
tccpe.c:1764:        : PE_GUI == pe_type ? "__winstart" : s1->unicode_mode ? "__wstart" : 
"__start"

static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
{
..............................................
   if (find_elf_sym(symtab_section, PE_STDSYM("WinMain","@16")))
       pe_type = PE_GUI;
   else
   if (find_elf_sym(symtab_section, PE_STDSYM("wWinMain","@16"))) {
       pe_type = PE_GUI;
       s1->unicode_mode = PE_GUI;
   } else
..............................................
and
..............................................
   unicode_mode = s1->unicode_mode;
   start_symbol =
       TCC_OUTPUT_MEMORY == s1->output_type
       ? PE_GUI == pe_type ? (unicode_mode ? "__wrunwinmain" : "__runwinmain")
           : (unicode_mode ? "_wmain" : "_main")
       : PE_DLL == pe_type ? PE_STDSYM("__dllstart","@12")
           : PE_GUI == pe_type ? (unicode_mode ? "__wwinstart": "__winstart")
               : (unicode_mode ? "__wstart" : "__start")
       ;
..............................................

==>
tccelf.c
ST_FUNC int tcc_load_object_file(TCCState *s1,
                               int fd, unsigned long file_offset)
{
..............................................
       /* add symbol */
       name = (char *) strtab + sym->st_name;
#ifdef TCC_TARGET_PE
       /* skip unused (undefined) */
       int unicode_mode = s1->unicode_mode;
       if ((unicode_mode == 3 /*PE_EXE*/ && strcmp(name, "main") != 0)
           || (unicode_mode == 2 /*PE_GUI*/
               && strcmp(name, PE_STDSYM("WinMain","@16")) != 0)
           || (unicode_mode == 0
               && strcmp(name, "wmain") != 0
               && strcmp(name, PE_STDSYM("wWinMain","@16")) != 0)
       )
#endif
       sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
                               sym->st_info, sym->st_other,
                               sym->st_shndx, name);
       old_to_new_syms[i] = sym_index;
   }
..............................................

-----------------------------------------------
win32\lib\wincrt1.c:12:int _winstart(void)
+++
-----------------------------------------------

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
More:

1. unknown codes?
findstr /s /n il- *
-------------------
Changelog:206:  462: Use LGPL with bcheck.c and il-gen.c
il-gen.c:81:#include "il-opcodes.h"
il-gen.c:87:#include "il-opcodes.h"

2. Does unix/linux platform always use main as program's entry? And what about
"C67/coff" (TMS320C67xx target) environment?
ref:
http://en.wikipedia.org/wiki/TMS320C67xx#Software_support
http://en.wikipedia.org/wiki/DSP/BIOS

3. Some stub thing.
Useless functions are also added when linking the executable file.
If the size of crt1.c and wincrt1.c increases, the size of the compiled file 
increases.

Maybe the Unicode and ASCII entry functions should be placed in seperate files,
for example: "crt1.c/crt1_w.c" and "wincrt1.c/wincrt1_w.c".

My tests confirmed it. TCC adds the whole codes in c a file or  a file's o file,
as there is no optimization for the "defined but not used" codes.

So, shall we split the  start_entry
(_winstart/_runwinmain and _wwinstart/_wrunwinmain)
for
PE_GUI/TCC_OUTPUT_MEMORY
into seperate files? Then, it can reduce the linked file size.

Attachment: test_tmain.c
Description: Binary data

Attachment: test_tWinMain.c
Description: Binary data

Attachment: view_useless_code.c
Description: Binary data

_______________________________________________
Tinycc-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

Reply via email to