diff --git a/.gitignore b/.gitignore index 549c630..c989b6b 100644 --- a/.gitignore +++ b/.gitignore @@ -41,16 +41,17 @@ win32/include/stddef.h win32/include/varargs.h win32/include/tcclib.h -tests/test.out* -tests/test*.out tests/tcctest[1234] tests/tcctest.gcc +tests/*.out* tests/*.ref tests/*.txt tests/*.gcc tests/*-cc* tests/*-tcc* tests/libtcc_test +tests/asm-c-connect +tests/asm-c-connect-sep tests/vla_test tests/hello tests/tests2/fred.txt diff --git a/Makefile b/Makefile index 8888149..3ae466f 100644 --- a/Makefile +++ b/Makefile @@ -239,14 +239,15 @@ FORCE: # -------------------------------------------------------------------------- # documentation and man page tcc-doc.html: tcc-doc.texi - -makeinfo --no-split --html --number-sections -o $@ $< + makeinfo --no-split --html --number-sections -o $@ $< || true tcc.1: tcc-doc.texi - -$(TOPSRC)/texi2pod.pl $< tcc.pod - -pod2man --section=1 --center="Tiny C Compiler" --release="$(VERSION)" tcc.pod > $@ + $(TOPSRC)/texi2pod.pl $< tcc.pod \ + && pod2man --section=1 --center="Tiny C Compiler" --release="$(VERSION)" tcc.pod >tmp.1 \ + && mv tmp.1 $@ || rm -f tmp.1 tcc-doc.info: tcc-doc.texi - -makeinfo $< + makeinfo $< || true # -------------------------------------------------------------------------- # install @@ -304,7 +305,7 @@ ifneq "$(wildcard $(LIBTCC1_U))" "" endif # the msys-git shell works to configure && make except it does not have install -ifeq ($(CONFIG_WIN32)-$(shell which install >/dev/null 2>&1 || echo no),yes-no) +ifeq "$(and $(CONFIG_WIN32),$(shell which install >/dev/null 2>&1 || echo no))" "no" install-win : INSTALL = cp install-win : INSTALLBIN = cp endif @@ -349,10 +350,10 @@ tests2.%: $(MAKE) -C tests/tests2 $@ clean: - rm -f $(PROGS) $(PROGS_CROSS) tcc_p$(EXESUF) tcc.pod + rm -f tcc$(EXESUF) tcc_p$(EXESUF) *-tcc$(EXESUF) tcc.pod rm -f *~ *.o *.a *.so* *.out *.log lib*.def *.exe *.dll a.out tags TAGS - @$(MAKE) -C tests $@ @$(MAKE) -C lib $@ + @$(MAKE) -C tests $@ distclean: clean rm -f config.h config.mak config.texi tcc.1 tcc-doc.info tcc-doc.html diff --git a/arm-link.c b/arm-link.c index aee35af..92a24eb 100644 --- a/arm-link.c +++ b/arm-link.c @@ -382,6 +382,12 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t /* Nothing to do. Normally used to indicate a dependency on a certain symbol (like for exception handling under EABI). */ return; + case R_ARM_RELATIVE: +#ifdef TCC_TARGET_PE + add32le(ptr, val - s1->pe_imagebase); +#endif + /* do nothing */ + return; default: fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n", type, (unsigned)addr, ptr, (unsigned)val); diff --git a/arm64-link.c b/arm64-link.c index 73e503e..59322c5 100644 --- a/arm64-link.c +++ b/arm64-link.c @@ -240,6 +240,12 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t #endif write64le(ptr, val - rel->r_addend); return; + case R_AARCH64_RELATIVE: +#ifdef TCC_TARGET_PE + add32le(ptr, val - s1->pe_imagebase); +#endif + /* do nothing */ + return; default: fprintf(stderr, "FIXME: handle reloc type %x at %x [%p] to %x\n", type, (unsigned)addr, ptr, (unsigned)val); diff --git a/i386-link.c b/i386-link.c index b446644..aea3c21 100644 --- a/i386-link.c +++ b/i386-link.c @@ -226,6 +226,9 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t write16le(ptr, read16le(ptr) + val - addr); return; case R_386_RELATIVE: +#ifdef TCC_TARGET_PE + add32le(ptr, val - s1->pe_imagebase); +#endif /* do nothing */ return; case R_386_COPY: diff --git a/tcc.c b/tcc.c index c347a06..cd887d1 100644 --- a/tcc.c +++ b/tcc.c @@ -182,9 +182,9 @@ static void print_search_dirs(TCCState *s) /* print_dirs("programs", NULL, 0); */ print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths); print_dirs("libraries", s->library_paths, s->nb_library_paths); + printf("libtcc1:\n %s/"TCC_LIBTCC1"\n", s->tcc_lib_path); #ifndef TCC_TARGET_PE print_dirs("crt", s->crt_paths, s->nb_crt_paths); - printf("libtcc1:\n %s/"TCC_LIBTCC1"\n", s->tcc_lib_path); printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s)); #endif } diff --git a/tcc.h b/tcc.h index 4fc273b..cd67973 100644 --- a/tcc.h +++ b/tcc.h @@ -489,14 +489,6 @@ typedef struct Sym { } Sym; /* section definition */ -/* XXX: use directly ELF structure for parameters ? */ -/* special flag to indicate that the section should not be linked to - the other ones */ -#define SHF_PRIVATE 0x80000000 - -/* special flag, too */ -#define SECTION_ABS ((void *)1) - typedef struct Section { unsigned long data_offset; /* current data offset */ unsigned char *data; /* section data */ @@ -795,15 +787,13 @@ struct TCCState { struct sym_attr *sym_attrs; int nb_sym_attrs; - /* tiny assembler state */ - ElfSym esym_dot; - #ifdef TCC_TARGET_PE /* PE info */ int pe_subsystem; unsigned pe_characteristics; unsigned pe_file_align; unsigned pe_stack_size; + addr_t pe_imagebase; # ifdef TCC_TARGET_X86_64 Section *uw_pdata; int uw_sym; @@ -1390,7 +1380,7 @@ ST_DATA Section *lbounds_section; /* contains local data bound description */ ST_FUNC void tccelf_bounds_new(TCCState *s); #endif /* symbol sections */ -ST_DATA Section *symtab_section, *strtab_section; +ST_DATA Section *symtab_section; /* debug sections */ ST_DATA Section *stab_section, *stabstr_section; @@ -1408,7 +1398,7 @@ ST_FUNC void section_reserve(Section *sec, unsigned long size); ST_FUNC Section *find_section(TCCState *s1, const char *name); ST_FUNC Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags); -ST_FUNC void put_extern_sym2(Sym *sym, Section *section, addr_t value, unsigned long size, int can_add_underscore); +ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, addr_t value, unsigned long size, int can_add_underscore); ST_FUNC void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size); #if PTR_SIZE == 4 ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type); @@ -1551,6 +1541,9 @@ ST_FUNC void gen_bounded_ptr_deref(void); #ifdef TCC_TARGET_X86_64 ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c); ST_FUNC void gen_opl(int op); +#ifdef TCC_TARGET_PE +ST_FUNC void gen_vla_result(int addr); +#endif #endif /* ------------ arm-gen.c ------------ */ diff --git a/tccasm.c b/tccasm.c index 355d158..c035c8b 100644 --- a/tccasm.c +++ b/tccasm.c @@ -32,7 +32,8 @@ ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n) } static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global); -static Sym sym_dot; +static Sym* asm_new_label(TCCState *s1, int label, int is_local); +static Sym* asm_new_label1(TCCState *s1, int label, int is_local, int sh_num, int value); static Sym *asm_label_find(int v) { @@ -73,6 +74,16 @@ ST_FUNC Sym* get_asm_sym(int name, Sym *csym) return sym; } +static Sym* asm_section_sym(TCCState *s1, Section *sec) +{ + char buf[100]; + int label = tok_alloc(buf, + snprintf(buf, sizeof buf, "L.%s", sec->name) + )->tok; + Sym *sym = asm_label_find(label); + return sym ? sym : asm_new_label1(s1, label, 1, sec->sh_num, 0); +} + /* We do not use the C expression parser to handle symbols. Maybe the C expression parser could be tweaked to do so. */ @@ -145,13 +156,9 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe) skip(')'); break; case '.': - pe->v = 0; - pe->sym = &sym_dot; - pe->pcrel = 0; - sym_dot.type.t = VT_ASM | VT_STATIC; - sym_dot.c = -1; - tcc_state->esym_dot.st_shndx = cur_text_section->sh_num; - tcc_state->esym_dot.st_value = ind; + pe->v = ind; + pe->sym = asm_section_sym(s1, cur_text_section); + pe->pcrel = 0; next(); break; default: @@ -368,29 +375,26 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local, /* A VT_EXTERN symbol, even if it has a section is considered overridable. This is how we "define" .set targets. Real definitions won't have VT_EXTERN set. */ - if (esym && esym->st_shndx != SHN_UNDEF && !(sym->type.t & VT_EXTERN)) { + if (esym && esym->st_shndx != SHN_UNDEF) { /* the label is already defined */ - if (is_local != 1) { - tcc_error("assembler label '%s' already defined", - get_tok_str(label, NULL)); - } else { - /* redefinition of local labels is possible */ + if (IS_ASM_SYM(sym) + && (is_local == 1 || (sym->type.t & VT_EXTERN))) goto new_label; - } + if (!(sym->type.t & VT_EXTERN)) + tcc_error("assembler label '%s' already defined", + get_tok_str(label, NULL)); } } else { new_label: sym = asm_label_push(label); } if (!sym->c) - put_extern_sym2(sym, NULL, 0, 0, 0); + put_extern_sym2(sym, SHN_UNDEF, 0, 0, 0); esym = elfsym(sym); esym->st_shndx = sh_num; esym->st_value = value; - if (is_local != 2) sym->type.t &= ~VT_EXTERN; - return sym; } diff --git a/tccelf.c b/tccelf.c index 080c72b..70d47e1 100644 --- a/tccelf.c +++ b/tccelf.c @@ -38,13 +38,18 @@ ST_DATA Section *bounds_section; /* contains global data bound description */ ST_DATA Section *lbounds_section; /* contains local data bound description */ #endif /* symbol sections */ -ST_DATA Section *symtab_section, *strtab_section; +ST_DATA Section *symtab_section; /* debug sections */ ST_DATA Section *stab_section, *stabstr_section; /* XXX: avoid static variable */ static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */ +/* special flag to indicate that the section should not be linked to the other ones */ +#define SHF_PRIVATE 0x80000000 +/* section is dynsymtab_section */ +#define SHF_DYNSYM 0x40000000 + /* ------------------------------------------------------------------------- */ ST_FUNC void tccelf_new(TCCState *s) @@ -63,11 +68,10 @@ ST_FUNC void tccelf_new(TCCState *s) symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0, ".strtab", ".hashtab", SHF_PRIVATE); - strtab_section = symtab_section->link; s->symtab = symtab_section; /* private symbol table for dynamic symbols */ - s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE, + s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE|SHF_DYNSYM, ".dynstrtab", ".dynhashtab", SHF_PRIVATE); get_sym_attr(s, 0, 1); @@ -128,6 +132,8 @@ ST_FUNC void tccelf_delete(TCCState *s1) /* free loaded dlls array */ dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls); tcc_free(s1->sym_attrs); + + symtab_section = NULL; /* for tccrun.c:rt_printline() */ } /* save section data state */ @@ -536,7 +542,7 @@ ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, goto do_patch; } else if (shndx == SHN_COMMON || shndx == bss_section->sh_num) { /* data symbol keeps precedence over common/bss */ - } else if (s == tcc_state->dynsymtab_section) { + } else if (s->sh_flags & SHF_DYNSYM) { /* we accept that two DLL define the same symbol */ } else if (esym->st_other & ST_ASM_SET) { /* If the existing symbol came from an asm .set @@ -779,7 +785,7 @@ ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve) for_each_elem(symtab, 1, sym, ElfW(Sym)) { sh_num = sym->st_shndx; if (sh_num == SHN_UNDEF) { - name = (char *) strtab_section->data + sym->st_name; + name = (char *) s1->symtab->link->data + sym->st_name; /* Use ld.so to resolve symbol for us (for tcc -run) */ if (do_resolve) { #if defined TCC_IS_NATIVE && !defined TCC_TARGET_PE diff --git a/tccgen.c b/tccgen.c index 7e10c18..e0b744e 100644 --- a/tccgen.c +++ b/tccgen.c @@ -285,10 +285,7 @@ ST_FUNC ElfSym *elfsym(Sym *s) { if (!s || !s->c) return NULL; - if (s->c == -1) - return &tcc_state->esym_dot; - else - return &((ElfSym *)symtab_section->data)[s->c]; + return &((ElfSym *)symtab_section->data)[s->c]; } /* apply storage attributes to Elf symbol */ @@ -338,11 +335,11 @@ ST_FUNC void update_storage(Sym *sym) /* update sym->c so that it points to an external symbol in section 'section' with value 'value' */ -ST_FUNC void put_extern_sym2(Sym *sym, Section *section, +ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, addr_t value, unsigned long size, int can_add_underscore) { - int sym_type, sym_bind, sh_num, info, other, t; + int sym_type, sym_bind, info, other, t; ElfSym *esym; const char *name; char buf1[256]; @@ -350,13 +347,6 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, char buf[32]; #endif - if (section == NULL) - sh_num = SHN_UNDEF; - else if (section == SECTION_ABS) - sh_num = SHN_ABS; - else - sh_num = section->sh_num; - if (!sym->c) { name = get_tok_str(sym->v, NULL); #ifdef CONFIG_TCC_BCHECK @@ -431,7 +421,8 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, ST_FUNC void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size) { - put_extern_sym2(sym, section, value, size, 1); + int sh_num = section ? section->sh_num : SHN_UNDEF; + put_extern_sym2(sym, sh_num, value, size, 1); } /* add a new relocation entry to symbol 'sym' in section 's' */ @@ -848,6 +839,7 @@ ST_FUNC Sym *external_global_sym(int v, CType *type, int r) } else if (IS_ASM_SYM(s)) { s->type.t = type->t | (s->type.t & VT_EXTERN); s->type.ref = type->ref; + update_storage(s); } return s; } @@ -862,9 +854,12 @@ static void patch_type(Sym *sym, CType *type) } if (IS_ASM_SYM(sym)) { - sym->type = *type; + /* stay static if both are static */ + sym->type.t = type->t & (sym->type.t | ~VT_STATIC); + sym->type.ref = type->ref; + } - } else if (!is_compatible_types(&sym->type, type)) { + if (!is_compatible_types(&sym->type, type)) { tcc_error("incompatible types for redefinition of '%s'", get_tok_str(sym->v, NULL)); @@ -876,10 +871,11 @@ static void patch_type(Sym *sym, CType *type) get_tok_str(sym->v, NULL)); if (0 == (type->t & VT_EXTERN)) { - /* put complete type */ - sym->type = *type; - /* use static from prototype */ - sym->type.t |= static_proto; + /* put complete type, use static from prototype */ + sym->type.t = (type->t & ~VT_STATIC) | static_proto; + if (type->t & VT_INLINE) + sym->type.t = type->t; + sym->type.ref = type->ref; } } else { @@ -6570,8 +6566,10 @@ static void init_putv(CType *type, Section *sec, unsigned long c) memcpy(ptr, &vtop->c.ld, 10); #ifdef __TINYC__ else if (sizeof (long double) == sizeof (double)) - __asm__("fldl %1\nfstpt %0\n" : "=m" (ptr) : "m" (vtop->c.ld)); + __asm__("fldl %1\nfstpt %0\n" : "=m" (*ptr) : "m" (vtop->c.ld)); #endif + else if (vtop->c.ld == 0.0) + ; else #endif if (sizeof(long double) == LDOUBLE_SIZE) @@ -7019,6 +7017,11 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, vla_runtime_type_size(type, &a); gen_vla_alloc(type, a); +#if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64 + /* on _WIN64, because of the function args scratch area, the + result of alloca differs from RSP and is returned in RAX. */ + gen_vla_result(addr), addr = (loc -= PTR_SIZE); +#endif gen_vla_sp_save(addr); vla_sp_loc = addr; vlas_in_scope++; @@ -7337,18 +7340,16 @@ found: type.t |= VT_EXTERN; sym = external_sym(v, &type, r, &ad); if (ad.alias_target) { - Section tsec; ElfSym *esym; Sym *alias_target; alias_target = sym_find(ad.alias_target); esym = elfsym(alias_target); if (!esym) tcc_error("unsupported forward __alias__ attribute"); - tsec.sh_num = esym->st_shndx; /* Local statics have a scope until now (for warnings), remove it here. */ sym->sym_scope = 0; - put_extern_sym2(sym, &tsec, esym->st_value, esym->st_size, 0); + put_extern_sym2(sym, esym->st_shndx, esym->st_value, esym->st_size, 0); } } else { if (type.t & VT_STATIC) diff --git a/tccpe.c b/tccpe.c index 7e7150c..a7266c9 100644 --- a/tccpe.c +++ b/tccpe.c @@ -954,7 +954,7 @@ static void pe_build_exports(struct pe_info *pe) /* automatically write exports to .def */ pstrcpy(buf, sizeof buf, pe->filename); strcpy(tcc_fileextension(buf), ".def"); - op = fopen(buf, "w"); + op = fopen(buf, "wb"); if (NULL == op) { tcc_error_noabort("could not create '%s': %s", buf, strerror(errno)); } else { @@ -967,7 +967,7 @@ static void pe_build_exports(struct pe_info *pe) for (ord = 0; ord < sym_count; ++ord) { p = sorted[ord], sym_index = p->index, name = p->name; - /* insert actual address later in pe_relocate_rva */ + /* insert actual address later in relocate_section() */ put_elf_reloc(symtab_section, pe->thunk, func_o, R_XXX_RELATIVE, sym_index); *(DWORD*)(pe->thunk->data + name_o) @@ -1181,26 +1181,6 @@ static int pe_assign_addresses (struct pe_info *pe) return 0; } -/* ------------------------------------------------------------- */ -static void pe_relocate_rva (struct pe_info *pe, Section *s) -{ - Section *sr = s->reloc; - ElfW_Rel *rel, *rel_end; - rel_end = (ElfW_Rel *)(sr->data + sr->data_offset); - for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) { - if (ELFW(R_TYPE)(rel->r_info) == R_XXX_RELATIVE) { - int sym_index = ELFW(R_SYM)(rel->r_info); - DWORD addr = s->sh_addr; - if (sym_index) { - ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index; - addr = sym->st_value; - } - // printf("reloc rva %08x %08x %s\n", (DWORD)rel->r_offset, addr, s->name); - *(DWORD*)(s->data + rel->r_offset) += addr - pe->imagebase; - } - } -} - /*----------------------------------------------------------------------------*/ static int pe_isafunc(int sym_index) @@ -1830,7 +1810,7 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack) /* put relocations on it */ for (n = o + sizeof *p; o < n; o += sizeof p->BeginAddress) - put_elf_reloc(symtab_section, pd, o, R_X86_64_RELATIVE, s1->uw_sym); + put_elf_reloc(symtab_section, pd, o, R_XXX_RELATIVE, s1->uw_sym); } #endif /* ------------------------------------------------------------- */ @@ -1979,11 +1959,11 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename) else if (filename) { pe_assign_addresses(&pe); relocate_syms(s1, s1->symtab, 0); + s1->pe_imagebase = pe.imagebase; for (i = 1; i < s1->nb_sections; ++i) { Section *s = s1->sections[i]; if (s->reloc) { relocate_section(s1, s); - pe_relocate_rva(&pe, s); } } pe.start_addr = (DWORD) @@ -1999,6 +1979,9 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename) pe.thunk = data_section; pe_build_imports(&pe); s1->runtime_main = pe.start_symbol; +#ifdef TCC_TARGET_X86_64 + s1->uw_pdata = find_section(s1, ".pdata"); +#endif #endif } diff --git a/tccrun.c b/tccrun.c index 20d72ce..9360164 100644 --- a/tccrun.c +++ b/tccrun.c @@ -238,6 +238,10 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) if (0 == mem) return offset + RUN_SECTION_ALIGNMENT; +#ifdef TCC_TARGET_PE + s1->pe_imagebase = mem; +#endif + /* relocate each section */ for(i = 1; i < s1->nb_sections; i++) { s = s1->sections[i]; @@ -306,11 +310,11 @@ static void *win64_add_function_table(TCCState *s1) RtlAddFunctionTable( (RUNTIME_FUNCTION*)p, s1->uw_pdata->data_offset / sizeof (RUNTIME_FUNCTION), - text_section->sh_addr + s1->pe_imagebase ); s1->uw_pdata = NULL; } - return p;; + return p; } static void win64_del_function_table(void *p) @@ -439,7 +443,7 @@ no_stabs: if (wanted_pc >= sym->st_value && wanted_pc < sym->st_value + sym->st_size) { pstrcpy(last_func_name, sizeof(last_func_name), - (char *) strtab_section->data + sym->st_name); + (char *) symtab_section->link->data + sym->st_name); func_addr = sym->st_value; goto found; } diff --git a/tcctools.c b/tcctools.c index 53d88be..1d4424e 100644 --- a/tcctools.c +++ b/tcctools.c @@ -374,7 +374,7 @@ usage: if (v) printf("-> %s\n", file); - op = fopen(outfile, "w"); + op = fopen(outfile, "wb"); if (NULL == op) { fprintf(stderr, "tcc: impdef: could not create output file: %s\n", outfile); goto the_end; diff --git a/tests/Makefile b/tests/Makefile index f06f39c..5f6777d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -51,9 +51,8 @@ ifndef CONFIG_cross TESTS := $(filter-out cross-%,$(TESTS)) endif -ifdef CONFIG_WIN32 - SEP = $(if $(findstring :\,$(PATH)),;,:) - PATH := $(CURDIR)/$(TOP)$(SEP)$(PATH) # for libtcc_test to find libtcc.dll +ifeq ($(OS),Windows_NT) # for libtcc_test to find libtcc.dll + PATH := $(CURDIR)/$(TOP)$(if $(findstring :\,$(PATH)),;,:)$(PATH) endif RUN_TCC = $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS) @@ -243,8 +242,9 @@ asm-c-connect-sep$(EXESUF): asm-c-connect-1.o asm-c-connect-2.o asm-c-connect-test: asm-c-connect$(EXESUF) asm-c-connect-sep$(EXESUF) @echo ------------ $@ ------------ - ./asm-c-connect$(EXESUF) - ./asm-c-connect-sep$(EXESUF) + ./asm-c-connect$(EXESUF) > asm-c-connect.out1 && cat asm-c-connect.out1 + ./asm-c-connect-sep$(EXESUF) > asm-c-connect.out2 && cat asm-c-connect.out2 + @diff -u asm-c-connect.out1 asm-c-connect.out2 && echo "ok" cross-test : @echo ------------ $@ ------------ diff --git a/tests/asm-c-connect-1.c b/tests/asm-c-connect-1.c index 1849b56..8a28d78 100644 --- a/tests/asm-c-connect-1.c +++ b/tests/asm-c-connect-1.c @@ -8,7 +8,7 @@ static int x1_c(void) { - printf("x1\n"); + printf(" x1"); return 1; } @@ -16,21 +16,30 @@ asm(".text;"_"x1: call "_"x1_c; ret"); void callx4(void); void callx5_again(void); + +void x6() +{ + printf(" x6-1"); +} + int main(int argc, char *argv[]) { + printf("*"); asm("call "_"x1"); asm("call "_"x2"); asm("call "_"x3"); callx4(); asm("call "_"x5"); callx5_again(); + x6(); + printf(" *\n"); return 0; } static int x2(void) { - printf("x2\n"); + printf(" x2"); return 2; } @@ -38,11 +47,11 @@ extern int x3(void); void x4(void) { - printf("x4\n"); + printf(" x4"); } void x5(void); void x5(void) { - printf("x5\n"); + printf(" x5"); } diff --git a/tests/asm-c-connect-2.c b/tests/asm-c-connect-2.c index 5dad26c..3440b40 100644 --- a/tests/asm-c-connect-2.c +++ b/tests/asm-c-connect-2.c @@ -1,19 +1,36 @@ #include +#if defined _WIN32 && !defined __TINYC__ +# define _ "_" +#else +# define _ +#endif + int x3(void) { - printf("x3\n"); + printf(" x3"); return 3; } /* That callx4 is defined globally (as if ".globl callx4") is a TCC extension. GCC doesn't behave like this. */ void callx4(void); -__asm__("callx4: call x4; ret"); +__asm__(_"callx4: call "_"x4; ret;" +#ifndef __TINYC__ + " .global "_"callx4" +#endif +); extern void x5(void); + void callx5_again(void); void callx5_again(void) { x5(); + asm("call "_"x6"); +} + +static void x6() +{ + printf(" x6-2"); } diff --git a/tests/tcctest.c b/tests/tcctest.c index 000523e..57670be 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -3370,6 +3370,37 @@ void test_asm_call(void) #endif } +#if defined __x86_64__ +# define RX "(%rip)" +#else +# define RX +#endif + +void asm_dot_test(void) +{ + int x; + for (x = 1;; ++x) { + int r = x; + switch (x) { + case 1: + asm(".text; lea S"RX",%eax; lea ."RX",%ecx; sub %ecx,%eax; S=.; jmp p0"); + case 2: + asm(".text; jmp .+6; .int 123; mov .-4"RX",%eax; jmp p0"); + case 3: + asm(".data; Y=.; .int 999; X=Y; .int 456; X=.-4"); + asm(".text; mov X"RX",%eax; jmp p0"); + case 4: + asm(".data; X=.; .int 789; Y=.; .int 999"); + asm(".text; mov X"RX",%eax; X=Y; jmp p0"); + case 0: + asm(".text; p0=.; mov %%eax,%0;" : "=m"(r)); break; + } + if (r == x) + break; + printf("asm_dot_test %d: %d\n", x, r); + } +} + void asm_test(void) { char buf[128]; @@ -3457,6 +3488,7 @@ void asm_test(void) trace_console(8, 8); test_asm_dead_code(); test_asm_call(); + asm_dot_test(); return; label1: goto label2; diff --git a/x86_64-gen.c b/x86_64-gen.c index d7cb895..e33a38a 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -1034,6 +1034,7 @@ void gfunc_epilog(void) saved_ind = ind; ind = func_sub_sp_offset - FUNC_PROLOG_SIZE; /* align local size to word & save local variables */ + func_scratch = (func_scratch + 15) & -16; v = (func_scratch + -loc + 15) & -16; if (v >= 4096) { @@ -2222,6 +2223,14 @@ ST_FUNC void gen_vla_sp_restore(int addr) { gen_modrm64(0x8b, TREG_RSP, VT_LOCAL, NULL, addr); } +#ifdef TCC_TARGET_PE +/* Save result of gen_vla_alloc onto the stack */ +ST_FUNC void gen_vla_result(int addr) { + /* mov %rax,addr(%rbp)*/ + gen_modrm64(0x89, TREG_RAX, VT_LOCAL, NULL, addr); +} +#endif + /* Subtract from the stack pointer, and push the resulting value onto the stack */ ST_FUNC void gen_vla_alloc(CType *type, int align) { #ifdef TCC_TARGET_PE diff --git a/x86_64-link.c b/x86_64-link.c index c0c5e13..a96144c 100644 --- a/x86_64-link.c +++ b/x86_64-link.c @@ -287,6 +287,9 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t add64le(ptr, val - s1->got->sh_addr); break; case R_X86_64_RELATIVE: +#ifdef TCC_TARGET_PE + add32le(ptr, val - s1->pe_imagebase); +#endif /* do nothing */ break; }