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
426 elimination in the linker */426 elimination in the linker */
427 gen_le32(pe->v + sym->jnext - ind - 4);427 gen_le32(pe->v + sym->jnext - ind - 4);
428 } else {428 } else {
429 if (sym && sym->type.t == VT_VOID) {
430 sym->type.t = VT_FUNC;
431 sym->type.ref = NULL;
432 }
429 gen_addrpc32(VT_SYM, sym, pe->v);433 gen_addrpc32(VT_SYM, sym, pe->v);
430 }434 }
431}435}
tcc.h+7−0
@@ -521,6 +521,10 @@ struct TCCState { · 520 unmodified lines
521 /* PE info */521 /* PE info */
522 int pe_subsystem;522 int pe_subsystem;
523 unsigned long pe_file_align;523 unsigned long pe_file_align;
524 struct pe_uw {
525 Section *pdata;
526 int sym_1, sym_2, offs_1;
527 } pe_unwind;
524#endif528#endif
525 529
526#ifndef TCC_TARGET_PE530#ifndef TCC_TARGET_PE
@@ -1167,6 +1171,9 @@ ST_FUNC int pe_output_file(TCCState * s1, const char *filename); · 640 unmodified lines
1167ST_FUNC int pe_dllimport(int r, SValue *sv, void (*fn)(int r, SValue *sv));1171ST_FUNC int pe_dllimport(int r, SValue *sv, void (*fn)(int r, SValue *sv));
1168/* tiny_impdef.c */1172/* tiny_impdef.c */
1169ST_FUNC char *get_export_names(FILE *fp);1173ST_FUNC char *get_export_names(FILE *fp);
1174#ifdef TCC_TARGET_X86_64
1175ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);
1176#endif
1170#endif1177#endif
1171 1178
1172/* ------------ tccrun.c ----------------- */1179/* ------------ tccrun.c ----------------- */
tccpe.c+60−2
@@ -289,6 +289,7 @@ enum { · 288 unmodified lines
289 sec_data ,289 sec_data ,
290 sec_bss ,290 sec_bss ,
291 sec_idata ,291 sec_idata ,
292 sec_pdata ,
292 sec_other ,293 sec_other ,
293 sec_rsrc ,294 sec_rsrc ,
294 sec_stab ,295 sec_stab ,
@@ -301,6 +302,7 @@ static const DWORD pe_sec_flags[] = { · 6 unmodified lines
301 0xC0000040, /* ".data" , */302 0xC0000040, /* ".data" , */
302 0xC0000080, /* ".bss" , */303 0xC0000080, /* ".bss" , */
303 0x40000040, /* ".idata" , */304 0x40000040, /* ".idata" , */
305 0x40000040, /* ".pdata" , */
304 0xE0000060, /* < other > , */306 0xE0000060, /* < other > , */
305 0x40000040, /* ".rsrc" , */307 0x40000040, /* ".rsrc" , */
306 0x42000802, /* ".stab" , */308 0x42000802, /* ".stab" , */
@@ -634,6 +636,10 @@ static int pe_write(struct pe_info *pe) · 327 unmodified lines
634 pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_RESOURCE, addr, size);636 pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_RESOURCE, addr, size);
635 break;637 break;
636 638
639 case sec_pdata:
640 pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_EXCEPTION, addr, size);
641 break;
642
637 case sec_stab:643 case sec_stab:
638 break;644 break;
639 }645 }
@@ -1037,6 +1043,8 @@ static int pe_section_class(Section *s) · 397 unmodified lines
1037 return sec_rsrc;1043 return sec_rsrc;
1038 if (0 == strcmp(name, ".iedat"))1044 if (0 == strcmp(name, ".iedat"))
1039 return sec_idata;1045 return sec_idata;
1046 if (0 == strcmp(name, ".pdata"))
1047 return sec_pdata;
1040 return sec_other;1048 return sec_other;
1041 } else if (type == SHT_NOBITS) {1049 } else if (type == SHT_NOBITS) {
1042 if (flags & SHF_WRITE)1050 if (flags & SHF_WRITE)
@@ -1086,7 +1094,7 @@ static int pe_assign_addresses (struct pe_info *pe) · 43 unmodified lines
1086#ifdef PE_MERGE_DATA1094#ifdef PE_MERGE_DATA
1087 if (c == sec_bss && pe->sec_count && si[-1].cls == sec_data) {1095 if (c == sec_bss && pe->sec_count && si[-1].cls == sec_data) {
1088 /* append .bss to .data */1096 /* 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;
1090 addr += s->data_offset;1098 addr += s->data_offset;
1091 si[-1].sh_size = addr - si[-1].sh_addr;1099 si[-1].sh_size = addr - si[-1].sh_addr;
1092 continue;1100 continue;
@@ -1162,7 +1170,7 @@ static void pe_relocate_rva (struct pe_info *pe, Section *s) · 69 unmodified lines
1162 ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index;1170 ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index;
1163 addr = sym->st_value;1171 addr = sym->st_value;
1164 }1172 }
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);
1166 *(DWORD*)(s->data + rel->r_offset) += addr - pe->imagebase;1174 *(DWORD*)(s->data + rel->r_offset) += addr - pe->imagebase;
1167 }1175 }
1168 }1176 }
@@ -1623,6 +1631,56 @@ ST_FUNC int pe_dllimport(int r, SValue *sv, void (*fn)(int r, SValue *sv)) · 454 unmodified lines
1623 return 1;1631 return 1;
1624}1632}
1625 1633
1634/* ------------------------------------------------------------- */
1635#ifdef TCC_TARGET_X86_64
1636ST_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
1626/* ------------------------------------------------------------- */1684/* ------------------------------------------------------------- */
1627#ifdef TCC_TARGET_X86_641685#ifdef TCC_TARGET_X86_64
1628#define PE_STDSYM(n,s) n1686#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
78 return ret;78 return ret;
79 }79 }
80#endif80#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
81 return (*prog_main)(argc, argv);88 return (*prog_main)(argc, argv);
82}89}
83 90
win32/include/_mingw.h+1−1
@@ -58,7 +58,7 @@ typedef unsigned __int64 uintptr_t; · 57 unmodified lines
58#define _AMD64_ 158#define _AMD64_ 1
59#define __x86_64 159#define __x86_64 1
60#define USE_MINGW_SETJMP_TWO_ARGS60#define USE_MINGW_SETJMP_TWO_ARGS
61#define mingw_getsp tinyc_getsp61#define mingw_getsp tinyc_getbp
62#else62#else
63typedef __int32 intptr_t;63typedef __int32 intptr_t;
64typedef unsigned __int32 uintptr_t;64typedef unsigned __int32 uintptr_t;
win32/lib/chkstk.S+11−3
@@ -57,11 +57,19 @@ P0: · 56 unmodified lines
57 jmp *8(%rax)57 jmp *8(%rax)
58 58
59/* ---------------------------------------------- */59/* ---------------------------------------------- */
60/* avoid msvcrt unwind stuff for setjmp/longjmp */60/* setjmp/longjmp support */
61 61
62.globl tinyc_getsp62.globl tinyc_no_getbp
63tinyc_getsp:63tinyc_no_getbp:
64 .byte 0x90
65
66.globl tinyc_getbp
67tinyc_getbp:
64 xor %rax,%rax68 xor %rax,%rax
69 cmp %al,tinyc_no_getbp(%rax)
70 je t1
71 mov %rbp,%rax
72t1:
65 ret73 ret
66 74
67/* ---------------------------------------------- */75/* ---------------------------------------------- */
x86_64-gen.c+232−104
@@ -527,16 +527,6 @@ void store(int r, SValue *v) · 526 unmodified lines
527 }527 }
528}528}
529 529
530static 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
540/* 'is_jmp' is '1' if it is a jump */530/* 'is_jmp' is '1' if it is a jump */
541static void gcall_or_jmp(int is_jmp)531static void gcall_or_jmp(int is_jmp)
542{532{
@@ -564,16 +554,238 @@ static void gcall_or_jmp(int is_jmp) · 21 unmodified lines
564}554}
565 555
566#ifdef TCC_TARGET_PE556#ifdef TCC_TARGET_PE
557
567#define REGN 4558#define REGN 4
568static const uint8_t arg_regs[] = {559static const uint8_t arg_regs[] = {
569 TREG_RCX, TREG_RDX, TREG_R8, TREG_R9560 TREG_RCX, TREG_RDX, TREG_R8, TREG_R9
570};561};
562
563static 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
569void 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
580void 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' */
677void 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 */
739void 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
571#else773#else
774
775static 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
572#define REGN 6785#define REGN 6
573static const uint8_t arg_regs[REGN] = {786static const uint8_t arg_regs[REGN] = {
574 TREG_RDI, TREG_RSI, TREG_RDX, TREG_RCX, TREG_R8, TREG_R9787 TREG_RDI, TREG_RSI, TREG_RDX, TREG_RCX, TREG_R8, TREG_R9
575};788};
576#endif
577 789
578/* Generate function call. The function address is pushed first, then790/* Generate function call. The function address is pushed first, then
579 all the parameters in call order. This functions pops all the791 all the parameters in call order. This functions pops all the
@@ -593,11 +805,9 @@ void gfunc_call(int nb_args) · 13 unmodified lines
593 args_size += type_size(&vtop->type, &align);805 args_size += type_size(&vtop->type, &align);
594 } else if ((vtop[-i].type.t & VT_BTYPE) == VT_LDOUBLE) {806 } else if ((vtop[-i].type.t & VT_BTYPE) == VT_LDOUBLE) {
595 args_size += 16;807 args_size += 16;
596#ifndef TCC_TARGET_PE
597 } else if (is_sse_float(vtop[-i].type.t)) {808 } else if (is_sse_float(vtop[-i].type.t)) {
598 nb_sse_args++;809 nb_sse_args++;
599 if (nb_sse_args > 8) args_size += 8;810 if (nb_sse_args > 8) args_size += 8;
600#endif
601 } else {811 } else {
602 nb_reg_args++;812 nb_reg_args++;
603 if (nb_reg_args > REGN) args_size += 8;813 if (nb_reg_args > REGN) args_size += 8;
@@ -611,10 +821,6 @@ void gfunc_call(int nb_args) · 7 unmodified lines
611 gen_reg = nb_reg_args;821 gen_reg = nb_reg_args;
612 sse_reg = nb_sse_args;822 sse_reg = nb_sse_args;
613 823
614#ifdef TCC_TARGET_PE
615 save_regs(0); /* save used temporary registers */
616#endif
617
618 /* adjust stack to align SSE boundary */824 /* adjust stack to align SSE boundary */
619 if (args_size &= 8) {825 if (args_size &= 8) {
620 o(0x50); /* push $rax */826 o(0x50); /* push $rax */
@@ -650,13 +856,8 @@ void gfunc_call(int nb_args) · 29 unmodified lines
650 g(0x00);856 g(0x00);
651 args_size += size;857 args_size += size;
652 } else if (is_sse_float(vtop->type.t)) {858 } else if (is_sse_float(vtop->type.t)) {
653#ifdef TCC_TARGET_PE
654 int j = --gen_reg;
655 if (j >= REGN) {
656#else
657 int j = --sse_reg;859 int j = --sse_reg;
658 if (j >= 8) {860 if (j >= 8) {
659#endif
660 gv(RC_FLOAT);861 gv(RC_FLOAT);
661 o(0x50); /* push $rax */862 o(0x50); /* push $rax */
662 /* movq %xmm0, (%rsp) */863 /* movq %xmm0, (%rsp) */
@@ -688,42 +889,6 @@ void gfunc_call(int nb_args) · 25 unmodified lines
688 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT ||889 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT ||
689 (vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {890 (vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
690 } else if (is_sse_float(vtop->type.t)) {891 } 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
727 int j = --sse_reg;892 int j = --sse_reg;
728 if (j < 8) {893 if (j < 8) {
729 gv(RC_FLOAT); /* only one float register */894 gv(RC_FLOAT); /* only one float register */
@@ -750,16 +915,10 @@ void gfunc_call(int nb_args) · 20 unmodified lines
750 o(0xc0 + r * 8 + j - 4);915 o(0xc0 + r * 8 + j - 4);
751 }916 }
752 }917 }
753#endif
754 }918 }
755 vtop--;919 vtop--;
756 }920 }
757 921
758#ifdef TCC_TARGET_PE
759 /* allocate scratch space */
760 gadd_sp(-8*REGN);
761 args_size += 8*REGN;
762#else
763 save_regs(0); /* save used temporary registers */922 save_regs(0); /* save used temporary registers */
764 923
765 /* Copy R10 and R11 into RDX and RCX, respectively */924 /* Copy R10 and R11 into RDX and RCX, respectively */
@@ -771,13 +930,13 @@ void gfunc_call(int nb_args) · 5 unmodified lines
771 }930 }
772 931
773 oad(0xb8, nb_sse_args < 8 ? nb_sse_args : 8); /* mov nb_sse_args, %eax */932 oad(0xb8, nb_sse_args < 8 ? nb_sse_args : 8); /* mov nb_sse_args, %eax */
774#endif
775 gcall_or_jmp(0);933 gcall_or_jmp(0);
776 if (args_size)934 if (args_size)
777 gadd_sp(args_size);935 gadd_sp(args_size);
778 vtop--;936 vtop--;
779}937}
780 938
939
781#define FUNC_PROLOG_SIZE 11940#define FUNC_PROLOG_SIZE 11
782 941
783static void push_arg_reg(int i) {942static void push_arg_reg(int i) {
@@ -793,15 +952,13 @@ void gfunc_prolog(CType *func_type) · 9 unmodified lines
793 Sym *sym;952 Sym *sym;
794 CType *type;953 CType *type;
795 954
796 func_ret_sub = 0;
797
798 sym = func_type->ref;955 sym = func_type->ref;
799 addr = PTR_SIZE * 2;956 addr = PTR_SIZE * 2;
800 loc = 0;957 loc = 0;
801 ind += FUNC_PROLOG_SIZE;958 ind += FUNC_PROLOG_SIZE;
802 func_sub_sp_offset = ind;959 func_sub_sp_offset = ind;
960 func_ret_sub = 0;
803 961
804#ifndef TCC_TARGET_PE
805 if (func_type->ref->c == FUNC_ELLIPSIS) {962 if (func_type->ref->c == FUNC_ELLIPSIS) {
806 int seen_reg_num, seen_sse_num, seen_stack_size;963 int seen_reg_num, seen_sse_num, seen_stack_size;
807 seen_reg_num = seen_sse_num = 0;964 seen_reg_num = seen_sse_num = 0;
@@ -857,7 +1014,6 @@ void gfunc_prolog(CType *func_type) · 49 unmodified lines
857 push_arg_reg(REGN-1-i);1014 push_arg_reg(REGN-1-i);
858 }1015 }
859 }1016 }
860#endif
861 1017
862 sym = func_type->ref;1018 sym = func_type->ref;
863 param_index = 0;1019 param_index = 0;
@@ -880,7 +1036,6 @@ void gfunc_prolog(CType *func_type) · 16 unmodified lines
880 type = &sym->type;1036 type = &sym->type;
881 size = type_size(type, &align);1037 size = type_size(type, &align);
882 size = (size + 3) & ~3;1038 size = (size + 3) & ~3;
883#ifndef TCC_TARGET_PE
884 if (is_sse_float(type->t)) {1039 if (is_sse_float(type->t)) {
885 if (sse_param_index < 8) {1040 if (sse_param_index < 8) {
886 /* save arguments passed by register */1041 /* save arguments passed by register */
@@ -893,21 +1048,12 @@ void gfunc_prolog(CType *func_type) · 6 unmodified lines
893 addr += size;1048 addr += size;
894 }1049 }
895 sse_param_index++;1050 sse_param_index++;
896 } else1051
897#endif1052 } else if ((type->t & VT_BTYPE) == VT_STRUCT ||
898 if ((type->t & VT_BTYPE) == VT_STRUCT ||
899 (type->t & VT_BTYPE) == VT_LDOUBLE) {1053 (type->t & VT_BTYPE) == VT_LDOUBLE) {
900 param_addr = addr;1054 param_addr = addr;
901 addr += size;1055 addr += size;
902 } else {1056 } 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
911 if (reg_param_index < REGN) {1057 if (reg_param_index < REGN) {
912 /* save arguments passed by register */1058 /* save arguments passed by register */
913 push_arg_reg(reg_param_index);1059 push_arg_reg(reg_param_index);
@@ -916,21 +1062,12 @@ void gfunc_prolog(CType *func_type) · 2 unmodified lines
916 param_addr = addr;1062 param_addr = addr;
917 addr += 8;1063 addr += 8;
918 }1064 }
919#endif
920 reg_param_index++;1065 reg_param_index++;
921 }1066 }
922 sym_push(sym->v & ~SYM_FIELD, type,1067 sym_push(sym->v & ~SYM_FIELD, type,
923 VT_LOCAL | VT_LVAL, param_addr);1068 VT_LOCAL | VT_LVAL, param_addr);
924 param_index++;1069 param_index++;
925 }1070 }
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
934}1071}
935 1072
936/* generate function epilog */1073/* generate function epilog */
@@ -950,23 +1087,14 @@ void gfunc_epilog(void) · 13 unmodified lines
950 v = (-loc + 15) & -16;1087 v = (-loc + 15) & -16;
951 saved_ind = ind;1088 saved_ind = ind;
952 ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;1089 ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
953#ifdef TCC_TARGET_PE1090 o(0xe5894855); /* push %rbp, mov %rsp, %rbp */
954 if (v >= 4096) {1091 o(0xec8148); /* sub rsp, stacksize */
955 Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);1092 gen_le32(v);
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 }
967 ind = saved_ind;1093 ind = saved_ind;
968}1094}
969 1095
1096#endif /* not PE */
1097
970/* generate a jump to a label */1098/* generate a jump to a label */
971int gjmp(int t)1099int gjmp(int t)
972{1100{

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