From 1f72143eef1bb98a55cd06109fb8d9a3954a45e8 Mon Sep 17 00:00:00 2001 From: sergei Date: Tue, 6 Aug 2013 07:34:50 +0000 Subject: [PATCH] * In preparation for fixing Mantis #24791: Copy related code from tcgx86.g_proc_entry to tcgx86_64.g_proc_entry, and remove win64-specific stuff from tcgx86 version. git-svn-id: trunk@25218 - --- compiler/x86/cgx86.pas | 38 +------------------ compiler/x86_64/cgcpu.pas | 79 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 40 deletions(-) diff --git a/compiler/x86/cgx86.pas b/compiler/x86/cgx86.pas index 97c27678dc..eab8cf609f 100644 --- a/compiler/x86/cgx86.pas +++ b/compiler/x86/cgx86.pas @@ -2513,41 +2513,11 @@ unit cgx86; inc(stackmisalignment,sizeof(pint)); include(rg[R_INTREGISTER].preserved_by_proc,RS_FRAME_POINTER_REG); list.concat(Taicpu.op_reg(A_PUSH,tcgsize2opsize[OS_ADDR],NR_FRAME_POINTER_REG)); - if (target_info.system=system_x86_64_win64) then - begin - list.concat(cai_seh_directive.create_reg(ash_pushreg,NR_FRAME_POINTER_REG)); - include(current_procinfo.flags,pi_has_unwind_info); - end; { Return address and FP are both on stack } current_asmdata.asmcfi.cfa_def_cfa_offset(list,2*sizeof(pint)); current_asmdata.asmcfi.cfa_offset(list,NR_FRAME_POINTER_REG,-(2*sizeof(pint))); - if current_procinfo.procdef.proctypeoption<>potype_exceptfilter then - list.concat(Taicpu.op_reg_reg(A_MOV,tcgsize2opsize[OS_ADDR],NR_STACK_POINTER_REG,NR_FRAME_POINTER_REG)) - else - begin - { load framepointer from hidden $parentfp parameter } - para:=tparavarsym(current_procinfo.procdef.paras[0]); - if not (vo_is_parentfp in para.varoptions) then - InternalError(201201142); - if (para.paraloc[calleeside].location^.loc<>LOC_REGISTER) or - (para.paraloc[calleeside].location^.next<>nil) then - InternalError(201201143); - list.concat(Taicpu.op_reg_reg(A_MOV,tcgsize2opsize[OS_ADDR], - para.paraloc[calleeside].location^.register,NR_FRAME_POINTER_REG)); - { Need only as much stack space as necessary to do the calls. - Exception filters don't have own local vars, and temps are 'mapped' - to the parent procedure. - maxpushedparasize is already aligned at least on x86_64. } - localsize:=current_procinfo.maxpushedparasize; - end; + list.concat(Taicpu.op_reg_reg(A_MOV,tcgsize2opsize[OS_ADDR],NR_STACK_POINTER_REG,NR_FRAME_POINTER_REG)); current_asmdata.asmcfi.cfa_def_cfa_register(list,NR_FRAME_POINTER_REG); - { - TODO: current framepointer handling is not compatible with Win64 at all: - Win64 expects FP to point to the top or into the middle of local area. - In FPC it points to the bottom, making it impossible to generate - UWOP_SET_FPREG unwind code if local area is > 240 bytes. - So for now pretend we never have a framepointer. - } end; { allocate stackframe space } @@ -2563,12 +2533,6 @@ unit cgx86; if current_procinfo.framepointer=NR_STACK_POINTER_REG then current_asmdata.asmcfi.cfa_def_cfa_offset(list,localsize+sizeof(pint)); current_procinfo.final_localsize:=localsize; - if (target_info.system=system_x86_64_win64) then - begin - if localsize<>0 then - list.concat(cai_seh_directive.create_offset(ash_stackalloc,localsize)); - include(current_procinfo.flags,pi_has_unwind_info); - end; end; end; end; diff --git a/compiler/x86_64/cgcpu.pas b/compiler/x86_64/cgcpu.pas index 8caaeffbea..1744378c3b 100644 --- a/compiler/x86_64/cgcpu.pas +++ b/compiler/x86_64/cgcpu.pas @@ -36,7 +36,7 @@ unit cgcpu; tcgx86_64 = class(tcgx86) procedure init_register_allocators;override; - procedure g_proc_entry(list : TAsmList; parasize:longint; nostackframe:boolean);override; + procedure g_proc_entry(list : TAsmList;localsize:longint; nostackframe:boolean);override; procedure g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);override; procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override; procedure g_local_unwind(list: TAsmList; l: TAsmLabel);override; @@ -109,7 +109,7 @@ unit cgcpu; end; - procedure tcgx86_64.g_proc_entry(list : TAsmList;parasize:longint;nostackframe:boolean); + procedure tcgx86_64.g_proc_entry(list : TAsmList;localsize:longint;nostackframe:boolean); var hitem: tlinkedlistitem; r: integer; @@ -117,13 +117,86 @@ unit cgcpu; templist: TAsmList; frame_offset: longint; suppress_endprologue: boolean; + stackmisalignment: longint; + para: tparavarsym; begin hitem:=list.last; { pi_has_unwind_info may already be set at this point if there are SEH directives in assembler body. In this case, .seh_endprologue is expected to be one of those directives, and not generated here. } suppress_endprologue:=(pi_has_unwind_info in current_procinfo.flags); - inherited g_proc_entry(list,parasize,nostackframe); + + { save old framepointer } + if not nostackframe then + begin + { return address } + stackmisalignment := sizeof(pint); + list.concat(tai_regalloc.alloc(current_procinfo.framepointer,nil)); + if current_procinfo.framepointer=NR_STACK_POINTER_REG then + CGmessage(cg_d_stackframe_omited) + else + begin + { push } + inc(stackmisalignment,sizeof(pint)); + list.concat(Taicpu.op_reg(A_PUSH,tcgsize2opsize[OS_ADDR],NR_FRAME_POINTER_REG)); + if (target_info.system=system_x86_64_win64) then + begin + list.concat(cai_seh_directive.create_reg(ash_pushreg,NR_FRAME_POINTER_REG)); + include(current_procinfo.flags,pi_has_unwind_info); + end; + { Return address and FP are both on stack } + current_asmdata.asmcfi.cfa_def_cfa_offset(list,2*sizeof(pint)); + current_asmdata.asmcfi.cfa_offset(list,NR_FRAME_POINTER_REG,-(2*sizeof(pint))); + if current_procinfo.procdef.proctypeoption<>potype_exceptfilter then + list.concat(Taicpu.op_reg_reg(A_MOV,tcgsize2opsize[OS_ADDR],NR_STACK_POINTER_REG,NR_FRAME_POINTER_REG)) + else + begin + { load framepointer from hidden $parentfp parameter } + para:=tparavarsym(current_procinfo.procdef.paras[0]); + if not (vo_is_parentfp in para.varoptions) then + InternalError(201201142); + if (para.paraloc[calleeside].location^.loc<>LOC_REGISTER) or + (para.paraloc[calleeside].location^.next<>nil) then + InternalError(201201143); + list.concat(Taicpu.op_reg_reg(A_MOV,tcgsize2opsize[OS_ADDR], + para.paraloc[calleeside].location^.register,NR_FRAME_POINTER_REG)); + { Need only as much stack space as necessary to do the calls. + Exception filters don't have own local vars, and temps are 'mapped' + to the parent procedure. + maxpushedparasize is already aligned at least on x86_64. } + localsize:=current_procinfo.maxpushedparasize; + end; + current_asmdata.asmcfi.cfa_def_cfa_register(list,NR_FRAME_POINTER_REG); + { + TODO: current framepointer handling is not compatible with Win64 at all: + Win64 expects FP to point to the top or into the middle of local area. + In FPC it points to the bottom, making it impossible to generate + UWOP_SET_FPREG unwind code if local area is > 240 bytes. + So for now pretend we never have a framepointer. + } + end; + + { allocate stackframe space } + if (localsize<>0) or + ((target_info.stackalign>sizeof(pint)) and + (stackmisalignment <> 0) and + ((pi_do_call in current_procinfo.flags) or + (po_assembler in current_procinfo.procdef.procoptions))) then + begin + if target_info.stackalign>sizeof(pint) then + localsize := align(localsize+stackmisalignment,target_info.stackalign)-stackmisalignment; + cg.g_stackpointer_alloc(list,localsize); + if current_procinfo.framepointer=NR_STACK_POINTER_REG then + current_asmdata.asmcfi.cfa_def_cfa_offset(list,localsize+sizeof(pint)); + current_procinfo.final_localsize:=localsize; + if (target_info.system=system_x86_64_win64) then + begin + if localsize<>0 then + list.concat(cai_seh_directive.create_offset(ash_stackalloc,localsize)); + include(current_procinfo.flags,pi_has_unwind_info); + end; + end; + end; if not (pi_has_unwind_info in current_procinfo.flags) then exit;