tmps : string;
pd : TProcdef;
ImplIntf : TImplementedInterface;
-{$ifdef cpuhighleveltarget}
wrapperpd: tprocdef;
wrapperinfo: pskpara_interface_wrapper;
-{$else}
- tmplist: tasmlist;
- oldfileposinfo: tfileposinfo;
-{$endif cpuhighleveltarget}
+ tmplist: tasmlist;
+ oldfileposinfo: tfileposinfo;
+ usehighlevelwrapper: Boolean;
begin
+{$if defined(cpuhighleveltarget)}
+ usehighlevelwrapper:=true;
+{$else defined(cpuhighleveltarget)}
+ { on PPC systems that use a TOC the linker needs to be able to insert
+ an instruction to restore the TOC register after every branch
+ between code fragments that use a different TOC (which has to be
+ executed when that "branch" returns). So we can't use tail call
+ branches to routines potentially using a different TOC there }
+ if target_info.system in systems_ppc_toc then
+ usehighlevelwrapper:=true
+ else
+ usehighlevelwrapper:=false;
+{$endif defined(cpuhighleveltarget)}
for i:=0 to _class.ImplementedInterfaces.count-1 do
begin
ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
not is_objectpascal_helper(tprocdef(pd).struct) then
tobjectdef(tprocdef(pd).struct).register_vmt_call(tprocdef(pd).extnumber);
tmps:=CreateWrapperName(_Class,ImplIntf,j,pd);
-{$ifdef cpuhighleveltarget}
- new(wrapperinfo);
- wrapperinfo^.pd:=pd;
- wrapperinfo^.offset:=ImplIntf.ioffset;
- { insert the wrapper procdef in the current unit's local
- symbol table, but set the owning "struct" to the current
- class (so self will have the correct type) }
- wrapperpd:=create_procdef_alias(pd,tmps,tmps,
- current_module.localsymtable,_class,
- tsk_interface_wrapper,wrapperinfo);
- include(wrapperpd.procoptions,po_noreturn);
-{$else cpuhighleveltarget}
- oldfileposinfo:=current_filepos;
- if pd.owner.iscurrentunit then
- current_filepos:=pd.fileinfo
- else
- begin
- current_filepos.moduleindex:=current_module.unit_index;
- current_filepos.fileindex:=1;
- current_filepos.line:=1;
- current_filepos.column:=1;
- end;
- { create wrapper code }
- tmplist:=tasmlist.create;
- new_section(tmplist,sec_code,tmps,target_info.alignment.procalign);
- tmplist.Concat(tai_function_name.create(tmps));
- hlcg.init_register_allocators;
- hlcg.g_intf_wrapper(tmplist,pd,tmps,ImplIntf.ioffset);
- hlcg.done_register_allocators;
- if ((cs_debuginfo in current_settings.moduleswitches) or
- (cs_use_lineinfo in current_settings.globalswitches)) and
- (target_dbg.id<>dbg_stabx) then
- current_debuginfo.insertlineinfo(tmplist);
- list.concatlist(tmplist);
- tmplist.Free;
- current_filepos:=oldfileposinfo;
-{$endif cpuhighleveltarget}
+
+ if usehighlevelwrapper then
+ begin
+ new(wrapperinfo);
+ wrapperinfo^.pd:=pd;
+ wrapperinfo^.offset:=ImplIntf.ioffset;
+ { insert the wrapper procdef in the current unit's local
+ symbol table, but set the owning "struct" to the current
+ class (so self will have the correct type) }
+ wrapperpd:=create_procdef_alias(pd,tmps,tmps,
+ current_module.localsymtable,_class,
+ tsk_interface_wrapper,wrapperinfo);
+ include(wrapperpd.implprocoptions,pio_thunk);
+ end
+ else
+ begin
+ oldfileposinfo:=current_filepos;
+ if pd.owner.iscurrentunit then
+ current_filepos:=pd.fileinfo
+ else
+ begin
+ current_filepos.moduleindex:=current_module.unit_index;
+ current_filepos.fileindex:=1;
+ current_filepos.line:=1;
+ current_filepos.column:=1;
+ end;
+ { create wrapper code }
+ tmplist:=tasmlist.create;
+ new_section(tmplist,sec_code,tmps,target_info.alignment.procalign);
+ tmplist.Concat(tai_function_name.create(tmps));
+ hlcg.init_register_allocators;
+ hlcg.g_intf_wrapper(tmplist,pd,tmps,ImplIntf.ioffset);
+ hlcg.done_register_allocators;
+ if ((cs_debuginfo in current_settings.moduleswitches) or
+ (cs_use_lineinfo in current_settings.globalswitches)) and
+ (target_dbg.id<>dbg_stabx) then
+ current_debuginfo.insertlineinfo(tmplist);
+ list.concatlist(tmplist);
+ tmplist.Free;
+ current_filepos:=oldfileposinfo;
+ end;
end;
end;
end;
reference_reset_base(tmpref, reg, 0, ctempposinvalid, sizeof(pint), []);
a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, tempreg);
- { save TOC pointer in stackframe }
- reference_reset_base(tmpref, NR_STACK_POINTER_REG, get_rtoc_offset, ctempposinvalid, 8, []);
- a_load_reg_ref(list, OS_ADDR, OS_ADDR, NR_RTOC, tmpref);
-
{ move actual function pointer to CTR register }
list.concat(taicpu.op_reg(A_MTCTR, tempreg));
end;
end;
+ { save current RTOC for restoration after calls if necessary }
+ if pi_do_call in current_procinfo.flags then
+ begin
+ reference_reset_base(href,NR_STACK_POINTER_REG,get_rtoc_offset,ctempposinvalid,target_info.stackalign,[]);
+ a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,href);
+ end;
+
{ CR register not used by FPC atm }
{ keep R1 allocated??? }