diff --git a/i386-gen.c b/i386-gen.c
index 9a8ceeeb..5ea70dfe 100644
--- a/i386-gen.c
+++ b/i386-gen.c
@@ -215,9 +215,10 @@ ST_FUNC void load(int r, SValue *sv)
     SValue v1;
 
 #ifdef TCC_TARGET_PE
-    if (pe_dllimport(r, sv, load))
-        return;
+    SValue v2;
+    sv = pe_getimport(sv, &v2);
 #endif
+
     fr = sv->r;
     ft = sv->type.t;
     fc = sv->c.ul;
@@ -283,9 +284,10 @@ ST_FUNC void store(int r, SValue *v)
     int fr, bt, ft, fc;
 
 #ifdef TCC_TARGET_PE
-    if (pe_dllimport(r, v, store))
-        return;
+    SValue v2;
+    v = pe_getimport(v, &v2);
 #endif
+
     ft = v->type.t;
     fc = v->c.ul;
     fr = v->r & VT_VALMASK;
diff --git a/libtcc.c b/libtcc.c
index cc1c6af6..ae80bc64 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -393,7 +393,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
                             unsigned long value, unsigned long size,
                             int can_add_underscore)
 {
-    int sym_type, sym_bind, sh_num, info, other, attr;
+    int sym_type, sym_bind, sh_num, info, other;
     ElfW(Sym) *esym;
     const char *name;
     char buf1[256];
@@ -405,26 +405,12 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
     else
         sh_num = section->sh_num;
 
-    other = attr = 0;
-
     if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
         sym_type = STT_FUNC;
-#ifdef TCC_TARGET_PE
-        if (sym->type.ref)
-            attr = sym->type.ref->r;
-        if (FUNC_EXPORT(attr))
-            other |= 1;
-        if (FUNC_CALL(attr) == FUNC_STDCALL)
-            other |= 2;
-#endif
     } else if ((sym->type.t & VT_BTYPE) == VT_VOID) {
         sym_type = STT_NOTYPE;
     } else {
         sym_type = STT_OBJECT;
-#ifdef TCC_TARGET_PE
-        if (sym->type.t & VT_EXPORT)
-            other |= 1;
-#endif
     }
 
     if (sym->type.t & VT_STATIC)
@@ -463,12 +449,27 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
             }
         }
 #endif
+        other = 0;
 
 #ifdef TCC_TARGET_PE
-        if ((other & 2) && can_add_underscore) {
-            sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr));
-            name = buf1;
-        } else
+        if (sym->type.t & VT_EXPORT)
+            other |= 1;
+        if (sym_type == STT_FUNC && sym->type.ref) {
+            int attr = sym->type.ref->r;
+            if (FUNC_EXPORT(attr))
+                other |= 1;
+            if (FUNC_CALL(attr) == FUNC_STDCALL && can_add_underscore) {
+                sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr) * PTR_SIZE);
+                name = buf1;
+                other |= 2;
+                can_add_underscore = 0;
+            }
+        } else {
+            if (find_elf_sym(tcc_state->dynsymtab_section, name))
+                other |= 4;
+            if (sym->type.t & VT_IMPORT)
+                other |= 4;
+        }
 #endif
         if (tcc_state->leading_underscore && can_add_underscore) {
             buf1[0] = '_';
@@ -482,7 +483,6 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
         esym->st_value = value;
         esym->st_size = size;
         esym->st_shndx = sh_num;
-        esym->st_other |= other;
     }
 }
 
@@ -1215,9 +1215,13 @@ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
 
 LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, void *val)
 {
+#ifdef TCC_TARGET_PE
+    pe_putimport(s, 0, name, val);
+#else
     add_elf_sym(symtab_section, (uplong)val, 0,
                 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
                 SHN_ABS, name);
+#endif
     return 0;
 }
 
diff --git a/tcc.h b/tcc.h
index 700d0c54..780c18e8 100644
--- a/tcc.h
+++ b/tcc.h
@@ -261,12 +261,13 @@ typedef struct DLLReference {
 /* GNUC attribute definition */
 typedef struct AttributeDef {
     unsigned
-      packed        : 1,
-      aligned       : 5, /* alignement (0..16) */
       func_call     : 3, /* calling convention (0..5), see below */
+      aligned       : 5, /* alignement (0..16) */
+      packed        : 1,
       func_export   : 1,
       func_import   : 1,
-      func_args     : 8;
+      func_args     : 5,
+      fill          : 16;
     struct Section *section;
 } AttributeDef;
 
@@ -1176,7 +1177,8 @@ ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str);
 ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd);
 ST_FUNC int pe_add_dll(struct TCCState *s, const char *libraryname);
 ST_FUNC int pe_output_file(TCCState * s1, const char *filename);
-ST_FUNC int pe_dllimport(int r, SValue *sv, void (*fn)(int r, SValue *sv));
+ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, const void *value);
+ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2);
 /* tiny_impdef.c */
 ST_FUNC char *get_export_names(FILE *fp);
 #ifdef TCC_TARGET_X86_64
diff --git a/tccgen.c b/tccgen.c
index b608c1fb..be8d80f9 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -1343,10 +1343,8 @@ static void gen_opic(int op)
             }
             goto general_case;
         } else if (c2 && (op == '+' || op == '-') &&
-                   (((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM)
-                    && !(vtop[-1].sym->type.t & VT_IMPORT))
-                   ||
-                   (vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_LOCAL)) {
+                   (((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM))
+                    || (vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_LOCAL)) {
             /* symbol + constant case */
             if (op == '-')
                 l2 = -l2;
@@ -2973,7 +2971,7 @@ static void post_type(CType *type, AttributeDef *ad)
                     type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
                     if ((pt.t & VT_BTYPE) == VT_VOID)
                         error("parameter declared as void");
-                    arg_size += (type_size(&pt, &align) + 3) & ~3;
+                    arg_size += (type_size(&pt, &align) + PTR_SIZE - 1) / PTR_SIZE;
                 } else {
                 old_proto:
                     n = tok;
@@ -5284,6 +5282,12 @@ ST_FUNC void decl(int l)
                     func_decl_list(sym);
             }
 
+#ifdef TCC_TARGET_PE
+            if (ad.func_import)
+                type.t |= VT_IMPORT;
+            if (ad.func_export)
+                type.t |= VT_EXPORT;
+#endif
             if (tok == '{') {
                 if (l == VT_LOCAL)
                     error("cannot use local functions");
@@ -5402,10 +5406,6 @@ ST_FUNC void decl(int l)
                         /* NOTE: as GCC, uninitialized global static
                            arrays of null size are considered as
                            extern */
-#ifdef TCC_TARGET_PE
-                        if (ad.func_import)
-                            type.t |= VT_IMPORT;
-#endif
                         external_sym(v, &type, r);
                     } else {
                         type.t |= (btype.t & VT_STATIC); /* Retain "static". */
@@ -5415,12 +5415,7 @@ ST_FUNC void decl(int l)
                             r |= l;
                         if (has_init)
                             next();
-#ifdef TCC_TARGET_PE
-                        if (ad.func_export)
-                            type.t |= VT_EXPORT;
-#endif
-                        decl_initializer_alloc(&type, &ad, r,
-                                               has_init, v, l);
+                        decl_initializer_alloc(&type, &ad, r, has_init, v, l);
                     }
                 }
                 if (tok != ',') {
@@ -5432,4 +5427,3 @@ ST_FUNC void decl(int l)
         }
     }
 }
-
diff --git a/tccpe.c b/tccpe.c
index 536f4cdb..e8321dc3 100644
--- a/tccpe.c
+++ b/tccpe.c
@@ -753,10 +753,10 @@ static struct import_symbol *pe_add_import(struct pe_info *pe, int sym_index)
     int dll_index;
     struct pe_import_info *p;
     struct import_symbol *s;
+    ElfW(Sym) *isym;
 
-    dll_index = ((ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index)->st_value;
-    if (0 == dll_index)
-        return NULL;
+    isym = (ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index;
+    dll_index = isym->st_size;
 
     i = dynarray_assoc ((void**)pe->imp_info, pe->imp_count, dll_index);
     if (-1 != i) {
@@ -804,14 +804,20 @@ static void pe_build_imports(struct pe_info *pe)
 
     for (i = 0; i < pe->imp_count; ++i) {
         IMAGE_IMPORT_DESCRIPTOR *hdr;
-        int k, n;
+        int k, n, dllindex;
         ADDR3264 v;
         struct pe_import_info *p = pe->imp_info[i];
-        const char *name = pe->s1->loaded_dlls[p->dll_index-1]->name;
+        const char *name;
+        DLLReference *dllref;
+
+        dllindex = p->dll_index;
+        if (dllindex)
+            name = (dllref = pe->s1->loaded_dlls[dllindex-1])->name;
+        else
+            name = "", dllref = NULL;
 
         /* put the dll name into the import header */
         v = put_elf_str(pe->thunk, name);
-
         hdr = (IMAGE_IMPORT_DESCRIPTOR*)(pe->thunk->data + dll_ptr);
         hdr->FirstThunk = thk_ptr + rva_base;
         hdr->OriginalFirstThunk = ent_ptr + rva_base;
@@ -832,10 +838,12 @@ static void pe_build_imports(struct pe_info *pe)
                 put_elf_str(pe->thunk, name);
 #ifdef TCC_IS_NATIVE
                 if (pe->type == PE_RUN) {
-                    DLLReference *dllref = pe->s1->loaded_dlls[imp_sym->st_value-1];
-                    if ( !dllref->handle )
-                        dllref->handle = LoadLibrary(dllref->name);
-                    v = (ADDR3264)GetProcAddress(dllref->handle, name);
+                    v = imp_sym->st_value;
+                    if (dllref) {
+                        if ( !dllref->handle )
+                            dllref->handle = LoadLibrary(dllref->name);
+                        v = (ADDR3264)GetProcAddress(dllref->handle, name);
+                    }
                     if (!v)
                         error_noabort("undefined symbol '%s'", name);
                 }
@@ -1214,9 +1222,6 @@ static int pe_check_symbols(struct pe_info *pe)
 
             if (0 == imp_sym)
                 goto not_found;
-            is = pe_add_import(pe, imp_sym);
-            if (!is)
-                goto not_found;
 
             if (type == STT_NOTYPE) {
                 /* symbols from assembler have no type, find out which */
@@ -1226,6 +1231,8 @@ static int pe_check_symbols(struct pe_info *pe)
                     type = STT_OBJECT;
             }
 
+            is = pe_add_import(pe, imp_sym);
+
             if (type == STT_FUNC) {
                 unsigned long offset = is->thk_offset;
                 if (offset) {
@@ -1424,6 +1431,75 @@ static void pe_print_sections(TCCState *s1, const char *fname)
 }
 #endif
 
+/* ------------------------------------------------------------- */
+/* helper function for load/store to insert one more indirection */
+
+ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2)
+{
+    Sym *sym;
+    ElfW(Sym) *esym;
+    int r2;
+
+    if ((sv->r & (VT_VALMASK|VT_SYM)) != (VT_CONST|VT_SYM) || (sv->r2 != VT_CONST))
+        return sv;
+    sym = sv->sym;
+    if ((sym->type.t & (VT_EXTERN|VT_STATIC)) != VT_EXTERN)
+        return sv;
+    if (!sym->c)
+        put_extern_sym(sym, NULL, 0, 0);
+    esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
+    if (!(esym->st_other & 4))
+        return sv;
+
+    // printf("import %04x %04x %04x %s\n", sv->type.t, sym->type.t, sv->r, get_tok_str(sv->sym->v, NULL));
+
+    memset(v2, 0, sizeof *v2);
+    v2->type.t = VT_PTR;
+    v2->r = VT_CONST | VT_SYM | VT_LVAL;
+    v2->sym = sv->sym;
+
+    r2 = get_reg(RC_INT);
+    load(r2, v2);
+    v2->r = r2;
+
+    if (sv->c.ui) {
+        vpushv(v2);
+        vpushi(sv->c.ui);
+        gen_opi('+');
+        *v2 = *vtop--;
+    }
+
+    v2->type.t = sv->type.t;
+    v2->r |= sv->r & VT_LVAL;
+    return v2;
+}
+
+ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, const void *value)
+{
+    return add_elf_sym(
+        s1->dynsymtab_section,
+        (uplong)value,
+        dllindex, /* st_size */
+        ELFW_ST_INFO(STB_GLOBAL, STT_NOTYPE),
+        0,
+        value ? SHN_ABS : SHN_UNDEF,
+        name
+        );
+}
+
+static int add_dllref(TCCState *s1, const char *dllname)
+{
+    DLLReference *dllref;
+    int i;
+    for (i = 0; i < s1->nb_loaded_dlls; ++i)
+        if (0 == strcmp(s1->loaded_dlls[i]->name, dllname))
+            return i + 1;
+    dllref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname));
+    strcpy(dllref->name, dllname);
+    dynarray_add((void ***) &s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
+    return s1->nb_loaded_dlls;
+}
+
 /* ------------------------------------------------------------- */
 
 static int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len)
@@ -1503,8 +1579,7 @@ static char *get_line(char *line, int size, FILE *fp)
 /* ------------------------------------------------------------- */
 static int pe_load_def(TCCState *s1, FILE *fp)
 {
-    DLLReference *dllref;
-    int state = 0, ret = -1;
+    int state = 0, ret = -1, dllindex = 0;
     char line[400], dllname[80], *p;
 
     for (;;) {
@@ -1528,16 +1603,11 @@ static int pe_load_def(TCCState *s1, FILE *fp)
             continue;
 
         case 2:
-            dllref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname));
-            strcpy(dllref->name, dllname);
-            dynarray_add((void ***) &s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
+            dllindex = add_dllref(s1, dllname);
             ++state;
 
         default:
-            add_elf_sym(s1->dynsymtab_section,
-                s1->nb_loaded_dlls, 0,
-                ELFW_ST_INFO(STB_GLOBAL, STT_FUNC), 0,
-                text_section->sh_num, p);
+            pe_putimport(s1, dllindex, p, NULL);
             continue;
         }
     }
@@ -1552,24 +1622,16 @@ quit:
 
 static int pe_load_dll(TCCState *s1, const char *dllname, FILE *fp)
 {
-    int i = 0;
     char *p, *q;
+    int index;
     p = get_export_names(fp);
-    if (p) {
-        DLLReference *dllref;
-        dllref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname));
-        strcpy(dllref->name, dllname);
-        dynarray_add((void ***) &s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
-        for (q = p, i = 0; *q; ++i) {
-            add_elf_sym(s1->dynsymtab_section,
-                s1->nb_loaded_dlls, 0,
-                ELFW_ST_INFO(STB_GLOBAL, STT_FUNC), 0,
-                text_section->sh_num, q);
-            q += 1 + strlen(q);
-        }
-        tcc_free(p);
-    }
-    return i ? 0 : -1;
+    if (!p)
+        return -1;
+    index = add_dllref(s1, dllname);
+    for (q = p; *q; q += 1 + strlen(q))
+        pe_putimport(s1, index, q, NULL);
+    tcc_free(p);
+    return 0;
 }
 
 /* ------------------------------------------------------------- */
@@ -1605,32 +1667,6 @@ ST_FUNC int pe_add_dll(struct TCCState *s, const char *libname)
     return -1;
 }
 
-/* ------------------------------------------------------------- */
-/* helper function for load/store to insert one more indirection */
-
-ST_FUNC int pe_dllimport(int r, SValue *sv, void (*fn)(int r, SValue *sv))
-{
-    int t;
-    if ((sv->r & (VT_VALMASK|VT_SYM|VT_CONST)) != (VT_SYM|VT_CONST))
-	return 0;
-    t = sv->sym->type.t;
-    if (0 == (t & VT_IMPORT))
-	return 0;
-
-    sv->sym->type.t = t & ~VT_IMPORT;
-    //printf("import %x %04x %s\n", t, ind, get_tok_str(sv->sym->v, NULL));
-
-    vpushv(sv);
-    vtop->type.t &= ~(VT_ARRAY|VT_IMPORT);
-    mk_pointer(&vtop->type);
-    indir();
-    fn(r, vtop);
-    --vtop;
-
-    sv->sym->type.t = t;
-    return 1;
-}
-
 /* ------------------------------------------------------------- */
 #ifdef TCC_TARGET_X86_64
 ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
@@ -1702,6 +1738,8 @@ static void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe)
         /* need this for 'tccelf.c:relocate_section()' */
         s1->output_type = TCC_OUTPUT_EXE;
     }
+    else
+        pe_type = PE_EXE;
 
     start_symbol =
         TCC_OUTPUT_MEMORY == s1->output_type
@@ -1731,9 +1769,12 @@ static void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe)
         }
     }
 
+    if (TCC_OUTPUT_MEMORY == s1->output_type)
+        pe_type = PE_RUN;
+
     if (start_symbol) {
         addr = (uplong)tcc_get_symbol_err(s1, start_symbol);
-        if (s1->output_type == TCC_OUTPUT_MEMORY && addr)
+        if (PE_RUN == pe_type && addr)
             /* for -run GUI's, put '_runwinmain' instead of 'main' */
             add_elf_sym(symtab_section,
                     addr, 0,
@@ -1823,7 +1864,6 @@ ST_FUNC int pe_output_file(TCCState * s1, const char *filename)
 #ifndef TCC_IS_NATIVE
         error_noabort("-run supported only on native platform");
 #endif
-        pe.type = PE_RUN;
         pe.thunk = data_section;
         pe_build_imports(&pe);
     }
diff --git a/win32/tools/tiny_impdef.c b/win32/tools/tiny_impdef.c
index b024a900..f801e0b5 100644
--- a/win32/tools/tiny_impdef.c
+++ b/win32/tools/tiny_impdef.c
@@ -60,6 +60,7 @@ int main(int argc, char **argv)
     fp = op = NULL;
     v = 0;
     ret = 1;
+    p = NULL;
 
     for (i = 1; i < argc; ++i) {
         const char *a = argv[i];
@@ -90,19 +91,20 @@ usage:
     if (0 == outfile[0])
     {
         strcpy(outfile, file_basename(infile));
-        p = strrchr(outfile, '.');
-        if (NULL == p)
-            p = strchr(outfile, 0);
-        strcpy(p, ".def");
+        q = strrchr(outfile, '.');
+        if (NULL == q)
+            q = strchr(outfile, 0);
+        strcpy(q, ".def");
     }
 
     file = infile;
+
 #ifdef _WIN32
-    for (pp = ext; *pp; ++pp)
-        if (SearchPath(NULL, file, *pp, sizeof path, path, NULL)) {
-            file = path;
-            break;
-        }
+    pp = ext;
+    do if (SearchPath(NULL, file, *pp, sizeof path, path, NULL)) {
+       file = path;
+       break;
+    } while (*pp++);
 #endif
 
     fp = fopen(file, "rb");
@@ -110,6 +112,14 @@ usage:
         fprintf(stderr, "tiny_impdef: no such file: %s\n", infile);
         goto the_end;
     }
+    if (v)
+        printf("--> %s\n", file);
+
+    p = get_export_names(fp);
+    if (NULL == p) {
+        fprintf(stderr, "tiny_impdef: could not get exported function names.\n");
+        goto the_end;
+    }
 
     op = fopen(outfile, "w");
     if (NULL == op) {
@@ -117,21 +127,11 @@ usage:
         goto the_end;
     }
 
-    if (v)
-        printf("--> %s\n", infile);
-
-    fprintf(op, "LIBRARY %s\n\nEXPORTS\n", file_basename(infile));
-    p = get_export_names(fp);
-    if (NULL == p) {
-        fprintf(stderr, "tiny_impdef: could not get exported function names.\n");
-        goto the_end;
-    }
-
+    fprintf(op, "LIBRARY %s\n\nEXPORTS\n", file_basename(file));
     for (q = p, i = 0; *q; ++i) {
         fprintf(op, "%s\n", q);
         q += strlen(q) + 1;
     }
-    free(p);
 
     if (v) {
         printf("<-- %s\n", outfile);
@@ -141,6 +141,8 @@ usage:
     ret = 0;
 
 the_end:
+    if (p)
+        free(p);
     if (fp)
         fclose(fp);
     if (op)
diff --git a/x86_64-gen.c b/x86_64-gen.c
index a80020fb..10003d16 100644
--- a/x86_64-gen.c
+++ b/x86_64-gen.c
@@ -335,8 +335,8 @@ void load(int r, SValue *sv)
     SValue v1;
 
 #ifdef TCC_TARGET_PE
-    if (pe_dllimport(r, sv, load))
-        return;
+    SValue v2;
+    sv = pe_getimport(sv, &v2);
 #endif
 
     fr = sv->r;
@@ -469,8 +469,8 @@ void store(int r, SValue *v)
     int pic = 0;
 
 #ifdef TCC_TARGET_PE
-    if (pe_dllimport(r, v, store))
-        return;
+    SValue v2;
+    v = pe_getimport(v, &v2);
 #endif
 
     ft = v->type.t;