History

win64: add tiny unwind data for setjmp/longjmp

This enables native unwind semantics with longjmp on win64 by putting an entry into the .pdata section for each compiled fuction. Also, the function now use a fixed stack and store arguments into X(%rsp) rather than using push.

grischka committed 16 years ago

Commit 50b040e1 parent 88a3cca7 files · +322 −110Browse files

Unified · Split

7 files
  1. i386-asm.c +4 −0
  2. tcc.h +7 −0
  3. tccpe.c +60 −2
  4. tccrun.c +7 −0
  5. win32/include/_mingw.h +1 −1
  6. win32/lib/chkstk.S +11 −3
  7. x86_64-gen.c +232 −104
i386-asm.c+4−0
@@ -426,6 +426,10 @@ static void gen_disp32(ExprValue *pe) · 425 unmodified lines
426426 elimination in the linker */
427427 gen_le32(pe->v + sym->jnext - ind - 4);
428428 } else {
429+ if (sym && sym->type.t == VT_VOID) {
430+ sym->type.t = VT_FUNC;
431+ sym->type.ref = NULL;
432+ }
429433 gen_addrpc32(VT_SYM, sym, pe->v);
430434 }
431435 }
tcc.h+7−0
@@ -521,6 +521,10 @@ struct TCCState { · 520 unmodified lines
521521 /* PE info */
522522 int pe_subsystem;
523523 unsigned long pe_file_align;
524+ struct pe_uw {
525+ Section *pdata;
526+ int sym_1, sym_2, offs_1;
527+ } pe_unwind;
524528 #endif
525529
526530 #ifndef TCC_TARGET_PE
@@ -1167,6 +1171,9 @@ ST_FUNC int pe_output_file(TCCState * s1, const char *filename); · 640 unmodified lines
11671171 ST_FUNC int pe_dllimport(int r, SValue *sv, void (*fn)(int r, SValue *sv));
11681172 /* tiny_impdef.c */
11691173 ST_FUNC char *get_export_names(FILE *fp);
1174+#ifdef TCC_TARGET_X86_64
1175+ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);
1176+#endif
11701177 #endif
11711178
11721179 /* ------------ tccrun.c ----------------- */
tccpe.c+60−2
@@ -289,6 +289,7 @@ enum { · 288 unmodified lines
289289 sec_data ,
290290 sec_bss ,
291291 sec_idata ,
292+ sec_pdata ,
292293 sec_other ,
293294 sec_rsrc ,
294295 sec_stab ,
@@ -301,6 +302,7 @@ static const DWORD pe_sec_flags[] = { · 6 unmodified lines
301302 0xC0000040, /* ".data" , */
302303 0xC0000080, /* ".bss" , */
303304 0x40000040, /* ".idata" , */
305+ 0x40000040, /* ".pdata" , */
304306 0xE0000060, /* < other > , */
305307 0x40000040, /* ".rsrc" , */
306308 0x42000802, /* ".stab" , */
@@ -634,6 +636,10 @@ static int pe_write(struct pe_info *pe) · 327 unmodified lines
634636 pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_RESOURCE, addr, size);
635637 break;
636638
639+ case sec_pdata:
640+ pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_EXCEPTION, addr, size);
641+ break;
642+
637643 case sec_stab:
638644 break;
639645 }
@@ -1037,6 +1043,8 @@ static int pe_section_class(Section *s) · 397 unmodified lines
10371043 return sec_rsrc;
10381044 if (0 == strcmp(name, ".iedat"))
10391045 return sec_idata;
1046+ if (0 == strcmp(name, ".pdata"))
1047+ return sec_pdata;
10401048 return sec_other;
10411049 } else if (type == SHT_NOBITS) {
10421050 if (flags & SHF_WRITE)
@@ -1086,7 +1094,7 @@ static int pe_assign_addresses (struct pe_info *pe) · 43 unmodified lines
10861094 #ifdef PE_MERGE_DATA
10871095 if (c == sec_bss && pe->sec_count && si[-1].cls == sec_data) {
10881096 /* append .bss to .data */
1089− s->sh_addr = addr = ((addr-1) | 15) + 1;
1097+ s->sh_addr = addr = ((addr-1) | (s->sh_addralign-1)) + 1;
10901098 addr += s->data_offset;
10911099 si[-1].sh_size = addr - si[-1].sh_addr;
10921100 continue;
@@ -1162,7 +1170,7 @@ static void pe_relocate_rva (struct pe_info *pe, Section *s) · 69 unmodified lines
11621170 ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index;
11631171 addr = sym->st_value;
11641172 }
1165− // printf("reloc rva %08x %08x\n", (DWORD)rel->r_offset, addr);
1173+ // printf("reloc rva %08x %08x %s\n", (DWORD)rel->r_offset, addr, s->name);
11661174 *(DWORD*)(s->data + rel->r_offset) += addr - pe->imagebase;
11671175 }
11681176 }
@@ -1623,6 +1631,56 @@ ST_FUNC int pe_dllimport(int r, SValue *sv, void (*fn)(int r, SValue *sv)) · 454 unmodified lines
16231631 return 1;
16241632 }
16251633
1634+/* ------------------------------------------------------------- */
1635+#ifdef TCC_TARGET_X86_64
1636+ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
1637+{
1638+ static const char uw_info[] = {
1639+ 0x01, // UBYTE: 3 Version , UBYTE: 5 Flags
1640+ 0x04, // UBYTE Size of prolog
1641+ 0x02, // UBYTE Count of unwind codes
1642+ 0x05, // UBYTE: 4 Frame Register (rbp), UBYTE: 4 Frame Register offset (scaled)
1643+ // USHORT * n Unwind codes array
1644+ // 0x0b, 0x01, 0xff, 0xff, // stack size
1645+ 0x04, 0x03, // set frame ptr (mov rsp -> rbp)
1646+ 0x01, 0x50 // push reg (rbp)
1647+ };
1648+
1649+ struct pe_uw *pe_uw = &tcc_state->pe_unwind;
1650+
1651+ Section *uw, *pd;
1652+ WORD *p1;
1653+ DWORD *p2;
1654+ unsigned o2;
1655+
1656+ uw = data_section;
1657+ pd = pe_uw->pdata;
1658+ if (NULL == pd)
1659+ {
1660+ pe_uw->pdata = pd = find_section(tcc_state, ".pdata");
1661+ pe_uw->pdata->sh_addralign = 4;
1662+ section_ptr_add(uw, -uw->data_offset & 3);
1663+ pe_uw->offs_1 = uw->data_offset;
1664+ p1 = section_ptr_add(uw, sizeof uw_info);
1665+ /* use one common entry for all functions */
1666+ memcpy(p1, uw_info, sizeof uw_info);
1667+ pe_uw->sym_1 = put_elf_sym(symtab_section, 0, 0, 0, 0, text_section->sh_num, NULL);
1668+ pe_uw->sym_2 = put_elf_sym(symtab_section, 0, 0, 0, 0, uw->sh_num, NULL);
1669+ }
1670+
1671+ o2 = pd->data_offset;
1672+ p2 = section_ptr_add(pd, 3 * sizeof (DWORD));
1673+ /* record this function */
1674+ p2[0] = start;
1675+ p2[1] = end;
1676+ p2[2] = pe_uw->offs_1;
1677+ /* put relocations on it */
1678+ put_elf_reloc(symtab_section, pd, o2, R_X86_64_RELATIVE, pe_uw->sym_1);
1679+ put_elf_reloc(symtab_section, pd, o2+4, R_X86_64_RELATIVE, pe_uw->sym_1);
1680+ put_elf_reloc(symtab_section, pd, o2+8, R_X86_64_RELATIVE, pe_uw->sym_2);
1681+}
1682+#endif
1683+
16261684 /* ------------------------------------------------------------- */
16271685 #ifdef TCC_TARGET_X86_64
16281686 #define PE_STDSYM(n,s) n
tccrun.c+7−0
@@ -78,6 +78,13 @@ int tcc_run(TCCState *s1, int argc, char **argv) · 77 unmodified lines
7878 return ret;
7979 }
8080 #endif
81+
82+#ifdef TCC_TARGET_PE
83+ {
84+ unsigned char *p = tcc_get_symbol(s1, "tinyc_no_getbp");
85+ if (p) *p = 0;
86+ }
87+#endif
8188 return (*prog_main)(argc, argv);
8289 }
8390
win32/include/_mingw.h+1−1
@@ -58,7 +58,7 @@ typedef unsigned __int64 uintptr_t; · 57 unmodified lines
5858 #define _AMD64_ 1
5959 #define __x86_64 1
6060 #define USE_MINGW_SETJMP_TWO_ARGS
61−#define mingw_getsp tinyc_getsp
61+#define mingw_getsp tinyc_getbp
6262 #else
6363 typedef __int32 intptr_t;
6464 typedef unsigned __int32 uintptr_t;
win32/lib/chkstk.S+11−3
@@ -57,11 +57,19 @@ P0: · 56 unmodified lines
5757 jmp *8(%rax)
5858
5959 /* ---------------------------------------------- */
60−/* avoid msvcrt unwind stuff for setjmp/longjmp */
60+/* setjmp/longjmp support */
6161
62−.globl tinyc_getsp
63−tinyc_getsp:
62+.globl tinyc_no_getbp
63+tinyc_no_getbp:
64+ .byte 0x90
65+
66+.globl tinyc_getbp
67+tinyc_getbp:
6468 xor %rax,%rax
69+ cmp %al,tinyc_no_getbp(%rax)
70+ je t1
71+ mov %rbp,%rax
72+t1:
6573 ret
6674
6775 /* ---------------------------------------------- */
x86_64-gen.c+232−104
@@ -527,16 +527,6 @@ void store(int r, SValue *v) · 526 unmodified lines
527527 }
528528 }
529529
530−static void gadd_sp(int val)
531−{
532− if (val == (char)val) {
533− o(0xc48348);
534− g(val);
535− } else {
536− oad(0xc48148, val); /* add $xxx, %rsp */
537− }
538−}
539−
540530 /* 'is_jmp' is '1' if it is a jump */
541531 static void gcall_or_jmp(int is_jmp)
542532 {
@@ -564,16 +554,238 @@ static void gcall_or_jmp(int is_jmp) · 21 unmodified lines
564554 }
565555
566556 #ifdef TCC_TARGET_PE
557+
567558 #define REGN 4
568559 static const uint8_t arg_regs[] = {
569560 TREG_RCX, TREG_RDX, TREG_R8, TREG_R9
570561 };
562+
563+static int func_scratch;
564+
565+/* Generate function call. The function address is pushed first, then
566+ all the parameters in call order. This functions pops all the
567+ parameters and the function address. */
568+
569+void gen_offs_sp(int b, int r, int d)
570+{
571+ if (d == (char)d) {
572+ o(b | 0x4000 | (r << 11));
573+ g(d);
574+ } else {
575+ o(b | 0x8000 | (r << 11));
576+ gen_le32(d);
577+ }
578+}
579+
580+void gfunc_call(int nb_args)
581+{
582+ int size, align, r, args_size, i, d, j, bt;
583+ int nb_reg_args, gen_reg;
584+
585+ /* calculate the number of integer/float arguments */
586+ nb_reg_args = 0;
587+ for(i = 0; i < nb_args; i++) {
588+ bt = (vtop[-i].type.t & VT_BTYPE);
589+ if (bt != VT_STRUCT && bt != VT_LDOUBLE)
590+ nb_reg_args++;
591+ }
592+
593+ args_size = (nb_reg_args < REGN ? REGN : nb_reg_args) * PTR_SIZE;
594+ save_regs(0); /* save used temporary registers */
595+
596+ /* for struct arguments, we need to call memcpy and the function
597+ call breaks register passing arguments we are preparing.
598+ So, we process arguments which will be passed by stack first. */
599+ for(i = 0; i < nb_args; i++) {
600+ SValue *sv = &vtop[-i];
601+ bt = (sv->type.t & VT_BTYPE);
602+ if (bt == VT_STRUCT) {
603+ size = type_size(&sv->type, &align);
604+ /* align to stack align size */
605+ size = (size + 15) & ~16;
606+ /* generate structure store */
607+ r = get_reg(RC_INT);
608+ o(0x48);
609+ gen_offs_sp(0x24048d, r, args_size);
610+ args_size += size;
611+
612+ /* generate memcpy call */
613+ vset(&sv->type, r | VT_LVAL, 0);
614+ *++vtop = *sv;
615+ vstore();
616+ --vtop;
617+
618+ } else if (bt == VT_LDOUBLE) {
619+
620+ gv(RC_ST0);
621+ gen_offs_sp(0x243cdb, 0, args_size);
622+ args_size += 16;
623+
624+ }
625+ }
626+
627+ if (func_scratch < args_size)
628+ func_scratch = args_size;
629+
630+ gen_reg = nb_reg_args;
631+ for(i = 0; i < nb_args; i++) {
632+ bt = (vtop->type.t & VT_BTYPE);
633+ if (bt == VT_STRUCT || bt == VT_LDOUBLE) {
634+ ; /* done */
635+
636+ } else if (is_sse_float(vtop->type.t)) {
637+ gv(RC_FLOAT); /* only one float register */
638+ j = --gen_reg;
639+ if (j >= REGN) {
640+ o(0x0f66),
641+ /* movq %xmm0, j*8(%rsp) */
642+ gen_offs_sp(0x2444d6, 0, j*8);
643+ } else {
644+ d = arg_regs[j];
645+ /* movaps %xmm0, %xmmN */
646+ o(0x280f);
647+ o(0xc0 + (j << 3));
648+ /* mov %xmm0, %rxx */
649+ o(0x66);
650+ o(0x7e0f48 + (d >= 8));
651+ o(0xc0 + (d & 7));
652+ }
653+ } else {
654+ r = gv(RC_INT);
655+ j = --gen_reg;
656+ if (j >= REGN) {
657+ o(0x48);
658+ gen_offs_sp(0x244489, r, j*8);
659+ } else {
660+ d = arg_regs[j];
661+ if (d != r) {
662+ o(0x8948 + (d >= 8));
663+ o(0xc0 + r*8 + (d & 7));
664+ }
665+ }
666+ }
667+ vtop--;
668+ }
669+ gcall_or_jmp(0);
670+ vtop--;
671+}
672+
673+
674+#define FUNC_PROLOG_SIZE 11
675+
676+/* generate function prolog of type 't' */
677+void gfunc_prolog(CType *func_type)
678+{
679+ int addr, align, size, reg_param_index, bt;
680+ Sym *sym;
681+ CType *type;
682+
683+ func_ret_sub = 0;
684+ func_scratch = 0;
685+ loc = 0;
686+
687+ addr = PTR_SIZE * 2;
688+ ind += FUNC_PROLOG_SIZE;
689+ func_sub_sp_offset = ind;
690+ reg_param_index = 0;
691+
692+ sym = func_type->ref;
693+
694+ /* if the function returns a structure, then add an
695+ implicit pointer parameter */
696+ func_vt = sym->type;
697+ if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
698+ gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
699+ reg_param_index++;
700+ addr += PTR_SIZE;
701+ }
702+
703+ /* define parameters */
704+ while ((sym = sym->next) != NULL) {
705+ type = &sym->type;
706+ bt = type->t & VT_BTYPE;
707+ if (bt == VT_STRUCT || bt == VT_LDOUBLE)
708+ continue;
709+ if (reg_param_index < REGN) {
710+ /* save arguments passed by register */
711+ gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
712+ }
713+ sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, addr);
714+ reg_param_index++;
715+ addr += PTR_SIZE;
716+ }
717+
718+ while (reg_param_index < REGN) {
719+ if (func_type->ref->c == FUNC_ELLIPSIS)
720+ gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
721+ reg_param_index++;
722+ addr += PTR_SIZE;
723+ }
724+
725+ sym = func_type->ref;
726+ while ((sym = sym->next) != NULL) {
727+ type = &sym->type;
728+ bt = type->t & VT_BTYPE;
729+ if (bt == VT_STRUCT || bt == VT_LDOUBLE) {
730+ size = type_size(type, &align);
731+ size = (size + 15) & -16;
732+ sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, addr);
733+ addr += size;
734+ }
735+ }
736+}
737+
738+/* generate function epilog */
739+void gfunc_epilog(void)
740+{
741+ int v, saved_ind;
742+
743+ o(0xc9); /* leave */
744+ if (func_ret_sub == 0) {
745+ o(0xc3); /* ret */
746+ } else {
747+ o(0xc2); /* ret n */
748+ g(func_ret_sub);
749+ g(func_ret_sub >> 8);
750+ }
751+
752+ saved_ind = ind;
753+ ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
754+ /* align local size to word & save local variables */
755+ v = (func_scratch + -loc + 15) & -16;
756+
757+ pe_add_unwind_data(ind, saved_ind, v);
758+
759+ if (v >= 4096) {
760+ Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
761+ oad(0xb8, v); /* mov stacksize, %eax */
762+ oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */
763+ greloc(cur_text_section, sym, ind-4, R_X86_64_PC32);
764+ o(0x90); /* fill for FUNC_PROLOG_SIZE = 11 bytes */
765+ } else {
766+ o(0xe5894855); /* push %rbp, mov %rsp, %rbp */
767+ o(0xec8148); /* sub rsp, stacksize */
768+ gen_le32(v);
769+ }
770+ ind = saved_ind;
771+}
772+
571773 #else
774+
775+static void gadd_sp(int val)
776+{
777+ if (val == (char)val) {
778+ o(0xc48348);
779+ g(val);
780+ } else {
781+ oad(0xc48148, val); /* add $xxx, %rsp */
782+ }
783+}
784+
572785 #define REGN 6
573786 static const uint8_t arg_regs[REGN] = {
574787 TREG_RDI, TREG_RSI, TREG_RDX, TREG_RCX, TREG_R8, TREG_R9
575788 };
576−#endif
577789
578790 /* Generate function call. The function address is pushed first, then
579791 all the parameters in call order. This functions pops all the
@@ -593,11 +805,9 @@ void gfunc_call(int nb_args) · 13 unmodified lines
593805 args_size += type_size(&vtop->type, &align);
594806 } else if ((vtop[-i].type.t & VT_BTYPE) == VT_LDOUBLE) {
595807 args_size += 16;
596−#ifndef TCC_TARGET_PE
597808 } else if (is_sse_float(vtop[-i].type.t)) {
598809 nb_sse_args++;
599810 if (nb_sse_args > 8) args_size += 8;
600−#endif
601811 } else {
602812 nb_reg_args++;
603813 if (nb_reg_args > REGN) args_size += 8;
@@ -611,10 +821,6 @@ void gfunc_call(int nb_args) · 7 unmodified lines
611821 gen_reg = nb_reg_args;
612822 sse_reg = nb_sse_args;
613823
614−#ifdef TCC_TARGET_PE
615− save_regs(0); /* save used temporary registers */
616−#endif
617−
618824 /* adjust stack to align SSE boundary */
619825 if (args_size &= 8) {
620826 o(0x50); /* push $rax */
@@ -650,13 +856,8 @@ void gfunc_call(int nb_args) · 29 unmodified lines
650856 g(0x00);
651857 args_size += size;
652858 } else if (is_sse_float(vtop->type.t)) {
653−#ifdef TCC_TARGET_PE
654− int j = --gen_reg;
655− if (j >= REGN) {
656−#else
657859 int j = --sse_reg;
658860 if (j >= 8) {
659−#endif
660861 gv(RC_FLOAT);
661862 o(0x50); /* push $rax */
662863 /* movq %xmm0, (%rsp) */
@@ -688,42 +889,6 @@ void gfunc_call(int nb_args) · 25 unmodified lines
688889 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT ||
689890 (vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
690891 } else if (is_sse_float(vtop->type.t)) {
691−#ifdef TCC_TARGET_PE
692− int j = --gen_reg;
693− if (j < REGN) {
694− int d = arg_regs[j];
695− gv(RC_FLOAT); /* only one float register */
696− /* movaps %xmm0, %xmmN */
697− o(0x280f);
698− o(0xc0 + (j << 3));
699− o(0x50);
700− o(0xd60f66); /* movq %xmm0, (%rsp) */
701− o(0x2404 + (j << 3));
702− if (d < 8) {
703− o(0x58 + d); /* pop d */
704− } else {
705− o(0x58);
706− o(0xc08949 + d - 8);
707− }
708− }
709− } else {
710− int j = --gen_reg;
711− /* simple type */
712− /* XXX: implicit cast ? */
713− if (j < REGN) {
714− int d = arg_regs[j];
715− r = gv(RC_INT);
716− if (d != r) {
717− if (d < 8) {
718− o(0x8948); /* mov */
719− o(0xc0 + r * 8 + d);
720− } else {
721− o(0x8949); /* mov */
722− o(0xc0 + r * 8 + d - 8);
723− }
724− }
725− }
726−#else
727892 int j = --sse_reg;
728893 if (j < 8) {
729894 gv(RC_FLOAT); /* only one float register */
@@ -750,16 +915,10 @@ void gfunc_call(int nb_args) · 20 unmodified lines
750915 o(0xc0 + r * 8 + j - 4);
751916 }
752917 }
753−#endif
754918 }
755919 vtop--;
756920 }
757921
758−#ifdef TCC_TARGET_PE
759− /* allocate scratch space */
760− gadd_sp(-8*REGN);
761− args_size += 8*REGN;
762−#else
763922 save_regs(0); /* save used temporary registers */
764923
765924 /* Copy R10 and R11 into RDX and RCX, respectively */
@@ -771,13 +930,13 @@ void gfunc_call(int nb_args) · 5 unmodified lines
771930 }
772931
773932 oad(0xb8, nb_sse_args < 8 ? nb_sse_args : 8); /* mov nb_sse_args, %eax */
774−#endif
775933 gcall_or_jmp(0);
776934 if (args_size)
777935 gadd_sp(args_size);
778936 vtop--;
779937 }
780938
939+
781940 #define FUNC_PROLOG_SIZE 11
782941
783942 static void push_arg_reg(int i) {
@@ -793,15 +952,13 @@ void gfunc_prolog(CType *func_type) · 9 unmodified lines
793952 Sym *sym;
794953 CType *type;
795954
796− func_ret_sub = 0;
797−
798955 sym = func_type->ref;
799956 addr = PTR_SIZE * 2;
800957 loc = 0;
801958 ind += FUNC_PROLOG_SIZE;
802959 func_sub_sp_offset = ind;
960+ func_ret_sub = 0;
803961
804−#ifndef TCC_TARGET_PE
805962 if (func_type->ref->c == FUNC_ELLIPSIS) {
806963 int seen_reg_num, seen_sse_num, seen_stack_size;
807964 seen_reg_num = seen_sse_num = 0;
@@ -857,7 +1014,6 @@ void gfunc_prolog(CType *func_type) · 49 unmodified lines
8571014 push_arg_reg(REGN-1-i);
8581015 }
8591016 }
860−#endif
8611017
8621018 sym = func_type->ref;
8631019 param_index = 0;
@@ -880,7 +1036,6 @@ void gfunc_prolog(CType *func_type) · 16 unmodified lines
8801036 type = &sym->type;
8811037 size = type_size(type, &align);
8821038 size = (size + 3) & ~3;
883−#ifndef TCC_TARGET_PE
8841039 if (is_sse_float(type->t)) {
8851040 if (sse_param_index < 8) {
8861041 /* save arguments passed by register */
@@ -893,21 +1048,12 @@ void gfunc_prolog(CType *func_type) · 6 unmodified lines
8931048 addr += size;
8941049 }
8951050 sse_param_index++;
896− } else
897−#endif
898− if ((type->t & VT_BTYPE) == VT_STRUCT ||
1051+
1052+ } else if ((type->t & VT_BTYPE) == VT_STRUCT ||
8991053 (type->t & VT_BTYPE) == VT_LDOUBLE) {
9001054 param_addr = addr;
9011055 addr += size;
9021056 } else {
903−#ifdef TCC_TARGET_PE
904− if (reg_param_index < REGN) {
905− /* save arguments passed by register */
906− gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
907− }
908− param_addr = addr;
909− addr += 8;
910−#else
9111057 if (reg_param_index < REGN) {
9121058 /* save arguments passed by register */
9131059 push_arg_reg(reg_param_index);
@@ -916,21 +1062,12 @@ void gfunc_prolog(CType *func_type) · 2 unmodified lines
9161062 param_addr = addr;
9171063 addr += 8;
9181064 }
919−#endif
9201065 reg_param_index++;
9211066 }
9221067 sym_push(sym->v & ~SYM_FIELD, type,
9231068 VT_LOCAL | VT_LVAL, param_addr);
9241069 param_index++;
9251070 }
926−#ifdef TCC_TARGET_PE
927− if (func_type->ref->c == FUNC_ELLIPSIS) {
928− for (i = reg_param_index; i < REGN; ++i) {
929− gen_modrm64(0x89, arg_regs[i], VT_LOCAL, NULL, addr);
930− addr += 8;
931− }
932− }
933−#endif
9341071 }
9351072
9361073 /* generate function epilog */
@@ -950,23 +1087,14 @@ void gfunc_epilog(void) · 13 unmodified lines
9501087 v = (-loc + 15) & -16;
9511088 saved_ind = ind;
9521089 ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
953−#ifdef TCC_TARGET_PE
954− if (v >= 4096) {
955− Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
956− oad(0xb8, v); /* mov stacksize, %eax */
957− oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */
958− greloc(cur_text_section, sym, ind-4, R_X86_64_PC32);
959− o(0x90); /* fill for FUNC_PROLOG_SIZE = 11 bytes */
960− } else
961−#endif
962− {
963− o(0xe5894855); /* push %rbp, mov %rsp, %rbp */
964− o(0xec8148); /* sub rsp, stacksize */
965− gen_le32(v);
966− }
1090+ o(0xe5894855); /* push %rbp, mov %rsp, %rbp */
1091+ o(0xec8148); /* sub rsp, stacksize */
1092+ gen_le32(v);
9671093 ind = saved_ind;
9681094 }
9691095
1096+#endif /* not PE */
1097+
9701098 /* generate a jump to a label */
9711099 int gjmp(int t)
9721100 {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t