* 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 -
This commit is contained in:
sergei 2013-08-06 07:34:50 +00:00
parent ea65e272dd
commit 1f72143eef
2 changed files with 77 additions and 40 deletions

View File

@ -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;

View File

@ -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 <frame_pointer> }
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;