From 0be098929a062d706057d7beb78666daa52bac49 Mon Sep 17 00:00:00 2001
From: grischka <grischka>
Date: Mon, 17 Oct 2016 23:24:01 +0200
Subject: [PATCH] tccpp_new/delete and other cleanups

---
 libtcc.c               |  61 ++++++++----------------
 tcc.c                  |  17 +++----
 tcc.h                  |  76 ++++++++++++++---------------
 tccasm.c               |   2 +-
 tccelf.c               |  26 +++++++++-
 tccgen.c               |  33 +++++--------
 tccpe.c                | 106 ++++++++++++++++++++++-------------------
 tccpp.c                |  11 +++--
 tccrun.c               |  22 ++++++---
 win32/include/_mingw.h |  40 +++++++++-------
 10 files changed, 203 insertions(+), 191 deletions(-)

diff --git a/libtcc.c b/libtcc.c
index 70f0f61f..1b4b3545 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -647,7 +647,7 @@ static int tcc_compile(TCCState *s1)
 {
     Sym *define_start;
 
-    preprocess_init(s1);
+    preprocess_start(s1);
     define_start = define_stack;
 
     if (setjmp(s1->error_jmp_buf) == 0) {
@@ -665,11 +665,11 @@ static int tcc_compile(TCCState *s1)
         decl(VT_CONST);
         if (tok != TOK_EOF)
             expect("declaration");
-        gen_inline_functions();
         tccgen_end(s1);
     }
-
     s1->error_set_jmp_enabled = 0;
+
+    free_inline_functions(s1);
     /* reset define stack, but keep -D and built-ins */
     free_defines(define_start);
     sym_pop(&global_stack, NULL);
@@ -730,10 +730,8 @@ static void tcc_cleanup(void)
 {
     if (NULL == tcc_state)
         return;
+    tccpp_delete(tcc_state);
     tcc_state = NULL;
-
-    preprocess_delete();
-
     /* free sym_pools */
     dynarray_reset(&sym_pools, &nb_sym_pools);
     /* reset symbol stack */
@@ -743,6 +741,7 @@ static void tcc_cleanup(void)
 LIBTCCAPI TCCState *tcc_new(void)
 {
     TCCState *s;
+
     tcc_cleanup();
 
     s = tcc_mallocz(sizeof(TCCState));
@@ -772,10 +771,8 @@ LIBTCCAPI TCCState *tcc_new(void)
 #else
     tcc_set_lib_path(s, CONFIG_TCCDIR);
 #endif
-
     tccelf_new(s);
-    preprocess_new();
-    s->include_stack_ptr = s->include_stack;
+    tccpp_new(s);
 
     /* we add dummy defines for some special macros to speed up tests
        and to have working defined() */
@@ -830,12 +827,6 @@ LIBTCCAPI TCCState *tcc_new(void)
     tcc_define_symbol(s, "_WIN32", NULL);
 # ifdef TCC_TARGET_X86_64
     tcc_define_symbol(s, "_WIN64", NULL);
-    /* Those are defined by Visual Studio */
-    tcc_define_symbol(s, "_M_X64", "100");
-    tcc_define_symbol(s, "_M_AMD64", "100");
-# else
-    /* Defined by Visual Studio. 300 == 80386. */
-    tcc_define_symbol(s, "_M_IX86", "300");
 # endif
 #else
     tcc_define_symbol(s, "__unix__", NULL);
@@ -894,10 +885,8 @@ LIBTCCAPI TCCState *tcc_new(void)
     /* define __GNUC__ to have some useful stuff from sys/cdefs.h
        that are unconditionally used in FreeBSDs other system headers :/ */
     tcc_define_symbol(s, "__GNUC__", "2");
-    tcc_define_symbol(s, "__GNUC_MINOR__", "1");
+    tcc_define_symbol(s, "__GNUC_MINOR__", "7");
     tcc_define_symbol(s, "__builtin_alloca", "alloca");
-    tcc_define_symbol(s, "__builtin_memcpy", "memcpy");
-    tcc_define_symbol(s, "__USER_LABEL_PREFIX__", "");
 #  endif
 # else
     tcc_define_symbol(s, "__WINT_TYPE__", "unsigned int");
@@ -973,27 +962,16 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
     }
 
 #ifdef CONFIG_TCC_BCHECK
-    /* if bound checking, then add corresponding sections */
     if (s->do_bounds_check) {
+        /* if bound checking, then add corresponding sections */
+        tccelf_bounds_new(s);
         /* define symbol */
         tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
-        /* create bounds sections */
-        bounds_section = new_section(s, ".bounds",
-                                     SHT_PROGBITS, SHF_ALLOC);
-        lbounds_section = new_section(s, ".lbounds",
-                                      SHT_PROGBITS, SHF_ALLOC);
     }
 #endif
-    /* add debug sections */
     if (s->do_debug) {
-        /* stab symbols */
-        stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
-        stab_section->sh_entsize = sizeof(Stab_Sym);
-        stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
-        put_elf_str(stabstr_section, "");
-        stab_section->link = stabstr_section;
-        /* put first entry */
-        put_stabs("", 0, 0, 0, 0);
+        /* add debug sections */
+        tccelf_stab_new(s);
     }
 
     tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
@@ -1205,7 +1183,7 @@ PUB_FUNC int tcc_add_library_err(TCCState *s, const char *libname)
 {
     int ret = tcc_add_library(s, libname);
     if (ret < 0)
-        tcc_error_noabort("cannot find library 'lib%s'", libname);
+        tcc_error_noabort("library 'lib%s' not found", libname);
     return ret;
 }
 
@@ -1939,18 +1917,17 @@ LIBTCCAPI int tcc_set_options(TCCState *s, const char *r)
     return ret;
 }
 
-PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time)
+PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time)
 {
-    double tt;
-    tt = (double)total_time / 1000000.0;
-    if (tt < 0.001)
-        tt = 0.001;
+    if (total_time < 1)
+        total_time = 1;
     if (total_bytes < 1)
         total_bytes = 1;
-    fprintf(stderr, "%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
+    fprintf(stderr, "%d idents, %d lines, %d bytes, %0.3f s, %u lines/s, %0.1f MB/s\n",
            tok_ident - TOK_IDENT, total_lines, total_bytes,
-           tt, (int)(total_lines / tt),
-           total_bytes / tt / 1000000.0);
+           (double)total_time/1000,
+           (unsigned)total_lines*1000/total_time,
+           (double)total_bytes/1000/total_time);
 }
 
 PUB_FUNC void tcc_set_environment(TCCState *s)
diff --git a/tcc.c b/tcc.c
index 99794e26..28f3ae94 100644
--- a/tcc.c
+++ b/tcc.c
@@ -244,17 +244,14 @@ static char *default_outputfile(TCCState *s, const char *first_file)
     return tcc_strdup(buf);
 }
 
-static int64_t getclock_us(void)
+static unsigned getclock_ms(void)
 {
 #ifdef _WIN32
-    LARGE_INTEGER frequency, t1;
-    QueryPerformanceFrequency(&frequency);
-    QueryPerformanceCounter(&t1);
-    return t1.QuadPart * 1000000LL / frequency.QuadPart;
+    return GetTickCount();
 #else
     struct timeval tv;
     gettimeofday(&tv, NULL);
-    return tv.tv_sec * 1000000LL + tv.tv_usec;
+    return tv.tv_sec*1000 + (tv.tv_usec+500)/1000;
 #endif
 }
 
@@ -262,7 +259,7 @@ int main(int argc, char **argv)
 {
     TCCState *s;
     int ret, optind, i;
-    int64_t start_time = 0;
+    unsigned start_time = 0;
     const char *first_file = NULL;
 
     s = tcc_new();
@@ -322,7 +319,7 @@ int main(int argc, char **argv)
     }
 
     if (s->do_bench)
-        start_time = getclock_us();
+        start_time = getclock_ms();
 
     /* compile or add each files or library */
     for(i = ret = 0; i < s->nb_files && ret == 0; i++) {
@@ -349,8 +346,6 @@ int main(int argc, char **argv)
             fclose(s->ppfp);
 
     } else if (0 == ret) {
-        if (s->do_bench)
-            tcc_print_stats(s, getclock_us() - start_time);
         if (s->output_type == TCC_OUTPUT_MEMORY) {
 #ifdef TCC_IS_NATIVE
             ret = tcc_run(s, argc - 1 - optind, argv + 1 + optind);
@@ -364,6 +359,8 @@ int main(int argc, char **argv)
         }
     }
 
+    if (s->do_bench)
+        tcc_print_stats(s, getclock_ms() - start_time);
     tcc_delete(s);
     return ret;
 }
diff --git a/tcc.h b/tcc.h
index 06731746..e82bae50 100644
--- a/tcc.h
+++ b/tcc.h
@@ -30,35 +30,29 @@
 #include <string.h>
 #include <errno.h>
 #include <math.h>
-#include <signal.h>
 #include <fcntl.h>
 #include <setjmp.h>
 #include <time.h>
-#include <sys/stat.h>          /* stat() */
 
 #ifndef _WIN32
 # include <unistd.h>
 # include <sys/time.h>
-# ifndef __OpenBSD__
-#  include <sys/ucontext.h>
-# endif
-# include <sys/mman.h>
 # ifndef CONFIG_TCC_STATIC
 #  include <dlfcn.h>
 # endif
 /* XXX: need to define this to use them in non ISOC99 context */
  extern float strtof (const char *__nptr, char **__endptr);
  extern long double strtold (const char *__nptr, char **__endptr);
+
 #else /* on _WIN32: */
 # include <windows.h>
-# include <sys/timeb.h>
 # include <io.h> /* open, close etc. */
 # include <direct.h> /* getcwd */
 # ifdef __GNUC__
 #  include <stdint.h>
 # endif
 # define inline __inline
-# define inp next_inp
+# define inp next_inp /* inp is an intrinsic on msvc */
 # define snprintf _snprintf
 # define vsnprintf _vsnprintf
 # ifndef __GNUC__
@@ -109,30 +103,7 @@
 #define PATHSEP ':'
 #endif
 
-#include "elf.h"
-#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
-# define ELFCLASSW ELFCLASS64
-# define ElfW(type) Elf##64##_##type
-# define ELFW(type) ELF##64##_##type
-# define ElfW_Rel ElfW(Rela)
-# define SHT_RELX SHT_RELA
-# define REL_SECTION_FMT ".rela%s"
-/* XXX: DLL with PLT would only work with x86-64 for now */
-# define TCC_OUTPUT_DLL_WITH_PLT
-#else
-# define ELFCLASSW ELFCLASS32
-# define ElfW(type) Elf##32##_##type
-# define ELFW(type) ELF##32##_##type
-# define ElfW_Rel ElfW(Rel)
-# define SHT_RELX SHT_REL
-# define REL_SECTION_FMT ".rel%s"
-#endif
-
-/* target address type */
-#define addr_t ElfW(Addr)
-
-#include "stab.h"
-#include "libtcc.h"
+/* -------------------------------------------- */
 
 /* parser debug */
 /* #define PARSE_DEBUG */
@@ -292,6 +263,32 @@
 /* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */
 #define TCC_LIBGCC USE_MUADIR(CONFIG_SYSROOT "/" CONFIG_LDDIR) "/libgcc_s.so.1"
 
+/* -------------------------------------------- */
+
+#include "libtcc.h"
+#include "elf.h"
+#include "stab.h"
+
+#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
+# define ELFCLASSW ELFCLASS64
+# define ElfW(type) Elf##64##_##type
+# define ELFW(type) ELF##64##_##type
+# define ElfW_Rel ElfW(Rela)
+# define SHT_RELX SHT_RELA
+# define REL_SECTION_FMT ".rela%s"
+/* XXX: DLL with PLT would only work with x86-64 for now */
+# define TCC_OUTPUT_DLL_WITH_PLT
+#else
+# define ELFCLASSW ELFCLASS32
+# define ElfW(type) Elf##32##_##type
+# define ELFW(type) ELF##32##_##type
+# define ElfW_Rel ElfW(Rel)
+# define SHT_RELX SHT_REL
+# define REL_SECTION_FMT ".rel%s"
+#endif
+/* target address type */
+#define addr_t ElfW(Addr)
+
 /* -------------------------------------------- */
 /* include the target specific definitions */
 
@@ -1137,7 +1134,7 @@ ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags);
 ST_FUNC void tcc_add_pragma_libs(TCCState *s1);
 PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);
 
-PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time);
+PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);
 PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv);
 PUB_FUNC void tcc_set_environment(TCCState *s);
 #ifdef _WIN32
@@ -1198,9 +1195,9 @@ ST_FUNC void preprocess(int is_bof);
 ST_FUNC void next_nomacro(void);
 ST_FUNC void next(void);
 ST_INLN void unget_tok(int last_tok);
-ST_FUNC void preprocess_init(TCCState *s1);
-ST_FUNC void preprocess_new(void);
-ST_FUNC void preprocess_delete(void);
+ST_FUNC void preprocess_start(TCCState *s1);
+ST_FUNC void tccpp_new(TCCState *s);
+ST_FUNC void tccpp_delete(TCCState *s);
 ST_FUNC int tcc_preprocess(TCCState *s1);
 ST_FUNC void skip(int c);
 ST_FUNC NORETURN void expect(const char *msg);
@@ -1250,8 +1247,9 @@ ST_DATA const char *funcname;
 
 ST_FUNC void tccgen_start(TCCState *s1);
 ST_FUNC void tccgen_end(TCCState *s1);
-
+ST_FUNC void free_inline_functions(TCCState *s);
 ST_FUNC void check_vstack(void);
+
 ST_INLN int is_float(int t);
 ST_FUNC int ieee_finite(double d);
 ST_FUNC void test_lvalue(void);
@@ -1290,7 +1288,6 @@ ST_FUNC void expr_prod(void);
 ST_FUNC void expr_sum(void);
 ST_FUNC void gexpr(void);
 ST_FUNC int expr_const(void);
-ST_FUNC void gen_inline_functions(void);
 ST_FUNC void decl(int l);
 #if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_C67
 ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size);
@@ -1332,6 +1329,9 @@ ST_DATA Section *stab_section, *stabstr_section;
 
 ST_FUNC void tccelf_new(TCCState *s);
 ST_FUNC void tccelf_delete(TCCState *s);
+ST_FUNC void tccelf_bounds_new(TCCState *s);
+ST_FUNC void tccelf_stab_new(TCCState *s);
+
 ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags);
 ST_FUNC void section_realloc(Section *sec, unsigned long new_size);
 ST_FUNC void *section_ptr_add(Section *sec, addr_t size);
diff --git a/tccasm.c b/tccasm.c
index 890956b5..911fd48d 100644
--- a/tccasm.c
+++ b/tccasm.c
@@ -868,7 +868,7 @@ ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
     Sym *define_start;
     int ret;
 
-    preprocess_init(s1);
+    preprocess_start(s1);
 
     /* default section is text */
     cur_text_section = text_section;
diff --git a/tccelf.c b/tccelf.c
index 8fe40c9f..a8ae48a3 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -69,6 +69,28 @@ ST_FUNC void tccelf_new(TCCState *s)
                                       ".dynhashtab", SHF_PRIVATE);
 }
 
+#ifdef CONFIG_TCC_BCHECK
+ST_FUNC void tccelf_bounds_new(TCCState *s)
+{
+    /* create bounds sections */
+    bounds_section = new_section(s, ".bounds",
+                                 SHT_PROGBITS, SHF_ALLOC);
+    lbounds_section = new_section(s, ".lbounds",
+                                  SHT_PROGBITS, SHF_ALLOC);
+}
+#endif
+
+ST_FUNC void tccelf_stab_new(TCCState *s)
+{
+    stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
+    stab_section->sh_entsize = sizeof(Stab_Sym);
+    stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
+    put_elf_str(stabstr_section, "");
+    stab_section->link = stabstr_section;
+    /* put first entry */
+    put_stabs("", 0, 0, 0, 0);
+}
+
 static void free_section(Section *s)
 {
     tcc_free(s->data);
@@ -616,7 +638,7 @@ ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
             name = (char *) strtab_section->data + sym->st_name;
             /* Use ld.so to resolve symbol for us (for tcc -run) */
             if (do_resolve) {
-#if defined TCC_IS_NATIVE && !defined _WIN32
+#if defined TCC_IS_NATIVE && !defined TCC_TARGET_PE
                 void *addr;
                 name = (char *) symtab_section->link->data + sym->st_name;
                 addr = dlsym(RTLD_DEFAULT, name);
@@ -1786,7 +1808,7 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
     tcc_add_pragma_libs(s1);
     /* add libc */
     if (!s1->nostdlib) {
-        tcc_add_library(s1, "c");
+        tcc_add_library_err(s1, "c");
 #ifdef CONFIG_USE_LIBGCC
         if (!s1->static_link) {
             tcc_add_file(s1, TCC_LIBGCC);
diff --git a/tccgen.c b/tccgen.c
index 2fadf769..fdd86543 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -90,6 +90,7 @@ ST_FUNC void vpush64(int ty, unsigned long long v);
 ST_FUNC void vpush(CType *type);
 ST_FUNC int gvtst(int inv, int t);
 ST_FUNC int is_btype_size(int bt);
+static void gen_inline_functions(TCCState *s);
 
 ST_INLN int is_float(int t)
 {
@@ -182,24 +183,11 @@ ST_FUNC void tccgen_start(TCCState *s1)
 #ifdef TCC_TARGET_ARM
     arm_init(s1);
 #endif
-
-#if 0
-    /* define 'void *alloca(unsigned int)' builtin function */
-    {
-        Sym *s1;
-
-        p = anon_sym++;
-        sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
-        s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
-        s1->next = NULL;
-        sym->next = s1;
-        sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
-    }
-#endif
 }
 
 ST_FUNC void tccgen_end(TCCState *s1)
 {
+    gen_inline_functions(s1);
     check_vstack();
     /* end of translation unit info */
     if (s1->do_debug) {
@@ -6513,7 +6501,7 @@ static void gen_function(Sym *sym)
     check_vstack();
 }
 
-ST_FUNC void gen_inline_functions(void)
+static void gen_inline_functions(TCCState *s)
 {
     Sym *sym;
     int inline_generated, i, ln;
@@ -6523,8 +6511,8 @@ ST_FUNC void gen_inline_functions(void)
     /* iterate while inline function are referenced */
     for(;;) {
         inline_generated = 0;
-        for (i = 0; i < tcc_state->nb_inline_fns; ++i) {
-            fn = tcc_state->inline_fns[i];
+        for (i = 0; i < s->nb_inline_fns; ++i) {
+            fn = s->inline_fns[i];
             sym = fn->sym;
             if (sym && sym->c) {
                 /* the function was used: generate its code and
@@ -6548,13 +6536,18 @@ ST_FUNC void gen_inline_functions(void)
             break;
     }
     file->line_num = ln;
+}
+
+ST_FUNC void free_inline_functions(TCCState *s)
+{
+    int i;
     /* free tokens of unused inline functions */
-    for (i = 0; i < tcc_state->nb_inline_fns; ++i) {
-        fn = tcc_state->inline_fns[i];
+    for (i = 0; i < s->nb_inline_fns; ++i) {
+        struct InlineFunc *fn = s->inline_fns[i];
         if (fn->sym)
             tok_str_free(fn->func_str.str);
     }
-    dynarray_reset(&tcc_state->inline_fns, &tcc_state->nb_inline_fns);
+    dynarray_reset(&s->inline_fns, &s->nb_inline_fns);
 }
 
 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
diff --git a/tccpe.c b/tccpe.c
index 04a63ea4..5169099b 100644
--- a/tccpe.c
+++ b/tccpe.c
@@ -20,6 +20,9 @@
 
 #include "tcc.h"
 
+#define PE_MERGE_DATA
+/* #define PE_PRINT_SECTIONS */
+
 #ifndef _WIN32
 #define stricmp strcasecmp
 #define strnicmp strncasecmp
@@ -29,9 +32,6 @@
 #define MAX_PATH 260
 #endif
 
-#define PE_MERGE_DATA
-/* #define PE_PRINT_SECTIONS */
-
 #ifdef TCC_TARGET_X86_64
 # define ADDR3264 ULONGLONG
 # define REL_TYPE_DIRECT R_X86_64_64
@@ -832,7 +832,7 @@ static void pe_build_imports(struct pe_info *pe)
                     if (dllref) {
                         if ( !dllref->handle )
                             dllref->handle = LoadLibrary(dllref->name);
-                        v = (ADDR3264)GetProcAddress(dllref->handle, ordinal?(LPCSTR)NULL+ordinal:name);
+                        v = (ADDR3264)GetProcAddress(dllref->handle, ordinal?(char*)0+ordinal:name);
                     }
                     if (!v)
                         tcc_error_noabort("can't build symbol '%s'", name);
@@ -1074,6 +1074,9 @@ static int pe_assign_addresses (struct pe_info *pe)
     struct section_info *si;
     Section *s;
 
+    if (PE_DLL == pe->type)
+        pe->reloc = new_section(pe->s1, ".reloc", SHT_PROGBITS, 0);
+
     // pe->thunk = new_section(pe->s1, ".iedat", SHT_PROGBITS, SHF_ALLOC);
 
     section_order = tcc_malloc(pe->s1->nb_sections * sizeof (int));
@@ -1801,7 +1804,54 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
     pe->type = pe_type;
 }
 
-ST_FUNC int pe_output_file(TCCState * s1, const char *filename)
+static void pe_set_options(TCCState * s1, struct pe_info *pe)
+{
+    if (PE_DLL == pe->type) {
+        /* XXX: check if is correct for arm-pe target */
+        pe->imagebase = 0x10000000;
+    } else {
+#if defined(TCC_TARGET_ARM)
+        pe->imagebase = 0x00010000;
+#else
+        pe->imagebase = 0x00400000;
+#endif
+    }
+
+#if defined(TCC_TARGET_ARM)
+    /* we use "console" subsystem by default */
+    pe->subsystem = 9;
+#else
+    if (PE_DLL == pe->type || PE_GUI == pe->type)
+        pe->subsystem = 2;
+    else
+        pe->subsystem = 3;
+#endif
+    /* Allow override via -Wl,-subsystem=... option */
+    if (s1->pe_subsystem != 0)
+        pe->subsystem = s1->pe_subsystem;
+
+    /* set default file/section alignment */
+    if (pe->subsystem == 1) {
+        pe->section_align = 0x20;
+        pe->file_align = 0x20;
+    } else {
+        pe->section_align = 0x1000;
+        pe->file_align = 0x200;
+    }
+
+    if (s1->section_align != 0)
+        pe->section_align = s1->section_align;
+    if (s1->pe_file_align != 0)
+        pe->file_align = s1->pe_file_align;
+
+    if ((pe->subsystem >= 10) && (pe->subsystem <= 12))
+        pe->imagebase = 0;
+
+    if (s1->has_text_addr)
+        pe->imagebase = s1->text_addr;
+}
+
+ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
 {
     int ret;
     struct pe_info pe;
@@ -1815,56 +1865,12 @@ ST_FUNC int pe_output_file(TCCState * s1, const char *filename)
     pe_add_runtime(s1, &pe);
     relocate_common_syms(); /* assign bss adresses */
     tcc_add_linker_symbols(s1);
+    pe_set_options(s1, &pe);
 
     ret = pe_check_symbols(&pe);
     if (ret)
         ;
     else if (filename) {
-        if (PE_DLL == pe.type) {
-            pe.reloc = new_section(pe.s1, ".reloc", SHT_PROGBITS, 0);
-            /* XXX: check if is correct for arm-pe target */
-            pe.imagebase = 0x10000000;
-        } else {
-#if defined(TCC_TARGET_ARM)
-            pe.imagebase = 0x00010000;
-#else
-            pe.imagebase = 0x00400000;
-#endif
-        }
-
-#if defined(TCC_TARGET_ARM)
-        /* we use "console" subsystem by default */
-        pe.subsystem = 9;
-#else
-        if (PE_DLL == pe.type || PE_GUI == pe.type)
-            pe.subsystem = 2;
-        else
-            pe.subsystem = 3;
-#endif
-        /* Allow override via -Wl,-subsystem=... option */
-        if (s1->pe_subsystem != 0)
-            pe.subsystem = s1->pe_subsystem;
-
-        /* set default file/section alignment */
-	if (pe.subsystem == 1) {
-	    pe.section_align = 0x20;
-	    pe.file_align = 0x20;
-	} else {
-	    pe.section_align = 0x1000;
-	    pe.file_align = 0x200;
-	}
-
-        if (s1->section_align != 0)
-            pe.section_align = s1->section_align;
-        if (s1->pe_file_align != 0)
-            pe.file_align = s1->pe_file_align;
-
-        if ((pe.subsystem >= 10) && (pe.subsystem <= 12))
-            pe.imagebase = 0;
-
-        if (s1->has_text_addr)
-            pe.imagebase = s1->text_addr;
-
         pe_assign_addresses(&pe);
         relocate_syms(s1, 0);
         for (i = 1; i < s1->nb_sections; ++i) {
diff --git a/tccpp.c b/tccpp.c
index 098012d9..b75603fc 100644
--- a/tccpp.c
+++ b/tccpp.c
@@ -3458,7 +3458,7 @@ ST_INLN void unget_tok(int last_tok)
     tok = last_tok;
 }
 
-ST_FUNC void preprocess_init(TCCState *s1)
+ST_FUNC void preprocess_start(TCCState *s1)
 {
     s1->include_stack_ptr = s1->include_stack;
     /* XXX: move that before to avoid having to initialize
@@ -3477,11 +3477,14 @@ ST_FUNC void preprocess_init(TCCState *s1)
         (parse_flags & PARSE_FLAG_ASM_FILE) ? IS_ID : 0;
 }
 
-ST_FUNC void preprocess_new(void)
+ST_FUNC void tccpp_new(TCCState *s)
 {
     int i, c;
     const char *p, *r;
 
+    /* might be used in error() before preprocess_start() */
+    s->include_stack_ptr = s->include_stack;
+
     /* init isid table */
     for(i = CH_EOF; i<128; i++)
         isidnum_table[i - CH_EOF]
@@ -3518,7 +3521,7 @@ ST_FUNC void preprocess_new(void)
     }
 }
 
-ST_FUNC void preprocess_delete(void)
+ST_FUNC void tccpp_delete(TCCState *s)
 {
     int i, n;
 
@@ -3683,7 +3686,7 @@ ST_FUNC int tcc_preprocess(TCCState *s1)
     const char *p;
     Sym *define_start;
 
-    preprocess_init(s1);
+    preprocess_start(s1);
     ch = file->buf_ptr[0];
     tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
     parse_flags = PARSE_FLAG_PREPROCESS
diff --git a/tccrun.c b/tccrun.c
index 2fcecd94..6d31e2f4 100644
--- a/tccrun.c
+++ b/tccrun.c
@@ -23,20 +23,28 @@
 /* only native compiler supports -run */
 #ifdef TCC_IS_NATIVE
 
+#ifndef _WIN32
+# include <sys/mman.h>
+#endif
+
 #ifdef CONFIG_TCC_BACKTRACE
+# ifndef _WIN32
+#  include <signal.h>
+#  ifndef __OpenBSD__
+#   include <sys/ucontext.h>
+#  endif
+# else
+#  define ucontext_t CONTEXT
+# endif
 ST_DATA int rt_num_callers = 6;
 ST_DATA const char **rt_bound_error_msg;
 ST_DATA void *rt_prog_main;
-#endif
-
-#ifdef _WIN32
-#define ucontext_t CONTEXT
+static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level);
+static void rt_error(ucontext_t *uc, const char *fmt, ...);
+static void set_exception_handler(void);
 #endif
 
 static void set_pages_executable(void *ptr, unsigned long length);
-static void set_exception_handler(void);
-static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level);
-static void rt_error(ucontext_t *uc, const char *fmt, ...);
 static int tcc_relocate_ex(TCCState *s1, void *ptr);
 
 #ifdef _WIN64
diff --git a/win32/include/_mingw.h b/win32/include/_mingw.h
index 2a1f6577..2e565a64 100644
--- a/win32/include/_mingw.h
+++ b/win32/include/_mingw.h
@@ -31,8 +31,9 @@
 #define __int16 short
 #define __int32 int
 #define __int64 long long
+#define _HAVE_INT64
 
-#define __cdecl __attribute__((__cdecl__))
+#define __cdecl
 #define __declspec(x) __attribute__((x))
 #define __unaligned __attribute__((packed))
 #define __fastcall __attribute__((fastcall))
@@ -71,12 +72,15 @@
 #define __stdcall
 #define _AMD64_ 1
 #define __x86_64 1
+#define _M_X64 100 /* Visual Studio */
+#define _M_AMD64 100 /* Visual Studio */
 #define USE_MINGW_SETJMP_TWO_ARGS
 #define mingw_getsp tinyc_getbp
 #define __TRY__
 #else
 #define __stdcall __attribute__((__stdcall__))
 #define _X86_ 1
+#define _M_IX86 300 /* Visual Studio */
 #define WIN32 1
 #define _USE_32BIT_TIME_T
 #define __TRY__ void __try__(void**), *_sehrec[6]; __try__(_sehrec);
@@ -89,34 +93,36 @@
 #define _WCHAR_T_DEFINED
 #define _UINTPTR_T_DEFINED
 #define _INTPTR_T_DEFINED
-
 #define _INTEGRAL_MAX_BITS 64
 
-typedef long __time32_t;
+#ifndef _TIME32_T_DEFINED
 #define _TIME32_T_DEFINED
-typedef __int64 __time64_t;
+typedef long __time32_t;
+#endif
+
+#ifndef _TIME64_T_DEFINED
 #define _TIME64_T_DEFINED
+typedef long long __time64_t;
+#endif
+
+#ifndef _TIME_T_DEFINED
+#define _TIME_T_DEFINED
 #ifdef _USE_32BIT_TIME_T
 typedef __time32_t time_t;
-#define _TIME_T_DEFINED
 #else
 typedef __time64_t time_t;
-#define _TIME_T_DEFINED
+#endif
 #endif
 
-#if 0 // defined in stddef.h
-typedef unsigned long size_t;
-typedef long ssize_t;
-typedef unsigned short wchar_t;
-#endif
-#define _SIZE_T_DEFINED
-#define _SSIZE_T_DEFINED
-#define _WCHAR_T_DEFINED
-
-typedef unsigned short wctype_t;
-typedef unsigned int wint_t;
+#ifndef _WCTYPE_T_DEFINED
 #define _WCTYPE_T_DEFINED
+typedef wchar_t wctype_t;
+#endif
+
+#ifndef _WINT_T
 #define _WINT_T
+typedef __WINT_TYPE__ wint_t;
+#endif
 
 typedef int errno_t;
 #define _ERRCODE_DEFINED