+ Compiler support for pic on darwin/i386. The i386 rtl still needs

to be made pic-safe (mainly accesses to the global default8087cw)
  * At the same time also made the non-pic code abi-compliant (access
    external data via indirect symbol pointers etc)

    Darwin/i386 also puts the got into a virtual register (like
    Darwin/ppc), a.o. because the register allocator fails to colour
    a routine in aasmcpu.pas if we take away ebx from it.

git-svn-id: trunk@8657 -
This commit is contained in:
Jonas Maebe 2007-09-26 21:42:27 +00:00
parent 4492ee39c5
commit 3266f4e483
6 changed files with 112 additions and 18 deletions

View File

@ -1135,6 +1135,16 @@ implementation
result := '.section __TEXT, .fpc, regular, no_dead_strip';
exit;
end;
sec_code:
begin
if (aname='fpc_geteipasebx') or
(aname='fpc_geteipasecx') then
begin
result:='.section __TEXT,__textcoal_nt,coalesced,pure_instructions'#10'.weak_definition '+aname+
#10'.private_extern '+aname;
exit;
end;
end;
end;
result := inherited sectionname(atype,aname,aorder);
end;

View File

@ -83,7 +83,8 @@ unit cgcpu;
procedure tcg386.init_register_allocators;
begin
inherited init_register_allocators;
if cs_create_pic in current_settings.moduleswitches then
if (target_info.system<>system_i386_darwin) and
(cs_create_pic in current_settings.moduleswitches) then
rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP])
else
rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_EBX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP]);
@ -494,12 +495,26 @@ unit cgcpu;
(pi_needs_got in current_procinfo.flags) and
not(po_kylixlocal in current_procinfo.procdef.procoptions) then
begin
current_module.requires_ebx_pic_helper:=true;
cg.a_call_name_static(list,'fpc_geteipasebx');
list.concat(taicpu.op_sym_ofs_reg(A_ADD,S_L,current_asmdata.RefAsmSymbol('_GLOBAL_OFFSET_TABLE_'),0,NR_PIC_OFFSET_REG));
list.concat(tai_regalloc.alloc(NR_PIC_OFFSET_REG,nil));
{ ecx could be used in leave procedures }
current_procinfo.got:=NR_EBX;
if (target_info.system<>system_i386_darwin) then
begin
current_module.requires_ebx_pic_helper:=true;
cg.a_call_name_static(list,'fpc_geteipasebx');
list.concat(taicpu.op_sym_ofs_reg(A_ADD,S_L,current_asmdata.RefAsmSymbol('_GLOBAL_OFFSET_TABLE_'),0,NR_PIC_OFFSET_REG));
list.concat(tai_regalloc.alloc(NR_PIC_OFFSET_REG,nil));
{ ecx could be used in leaf procedures }
current_procinfo.got:=NR_EBX;
end
else
begin
{ can't use ecx, since that one may overwrite a parameter }
current_module.requires_ebx_pic_helper:=true;
cg.a_call_name_static(list,'fpc_geteipasebx');
list.concat(tai_regalloc.alloc(NR_EBX,nil));
a_label(list,current_procinfo.CurrGotLabel);
{ got is already set by ti386procinfo.allocate_got_register }
list.concat(tai_regalloc.dealloc(NR_EBX,nil));
a_load_reg_reg(list,OS_ADDR,OS_ADDR,NR_EBX,current_procinfo.got);
end;
end;
end;

View File

@ -28,7 +28,7 @@ unit cpupi;
interface
uses
psub,procinfo;
psub,procinfo,aasmdata;
type
ti386procinfo = class(tcgprocinfo)
@ -36,6 +36,7 @@ unit cpupi;
procedure set_first_temp_offset;override;
function calc_stackframe_size:longint;override;
procedure generate_parameter_info;override;
procedure allocate_got_register(list: tasmlist);override;
end;
@ -43,8 +44,8 @@ unit cpupi;
uses
cutils,
systems,globals,
tgobj,
systems,globals,globtype,
cgobj,tgobj,
cpubase,
cgutils,
symconst;
@ -88,6 +89,14 @@ unit cpupi;
para_stack_size := 0;
end;
procedure ti386procinfo.allocate_got_register(list: tasmlist);
begin
if (target_info.system = system_i386_darwin) and
(cs_create_pic in current_settings.moduleswitches) then
begin
got := cg.getaddressregister(list);
end;
end;
begin
cprocinfo:=ti386procinfo;

View File

@ -460,7 +460,7 @@ unit i_bsd;
system : system_i386_darwin;
name : 'Darwin for i386';
shortname : 'Darwin';
flags : [tf_p_ext_support,tf_files_case_aware,tf_smartlink_sections,tf_dwarf_relative_addresses,tf_dwarf_only_local_labels];
flags : [tf_p_ext_support,tf_files_case_aware,tf_smartlink_sections,tf_dwarf_relative_addresses,tf_dwarf_only_local_labels,tf_pic_uses_got];
cpu : cpu_i386;
unit_env : 'BSDUNITS';
extradefines : 'UNIX;BSD;HASUNIX';

View File

@ -113,6 +113,8 @@ interface
owner.AsmWrite(gas_regname(segment)+':');
if assigned(symbol) then
owner.AsmWrite(symbol.name);
if assigned(relsymbol) then
owner.AsmWrite('-'+relsymbol.name);
if ref.refaddr=addr_pic then
{$ifdef x86_64}
owner.AsmWrite('@GOTPCREL');

View File

@ -347,6 +347,9 @@ unit cgx86;
var
hreg : tregister;
href : treference;
{$ifndef x86_64}
add_hreg: boolean;
{$endif not x86_64}
begin
{$ifdef x86_64}
{ Only 32bit is allowed }
@ -403,18 +406,45 @@ unit cgx86;
end;
end;
{$else x86_64}
if (cs_create_pic in current_settings.moduleswitches) and
assigned(ref.symbol) and not((ref.symbol.bind=AB_LOCAL) and (ref.symbol.typ in [AT_LABEL,AT_FUNCTION])) then
add_hreg:=false;
if (target_info.system=system_i386_darwin) then
begin
if assigned(ref.symbol) and
not(assigned(ref.relsymbol)) and
((ref.symbol.bind = AB_EXTERNAL) or
(cs_create_pic in current_settings.moduleswitches)) then
begin
if (ref.symbol.bind = AB_EXTERNAL) or
((cs_create_pic in current_settings.moduleswitches) and
(ref.symbol.bind in [AB_COMMON,AB_GLOBAL])) then
begin
hreg:=g_indirect_sym_load(list,ref.symbol.name);
ref.symbol:=nil;
end
else
begin
include(current_procinfo.flags,pi_needs_got);
hreg:=current_procinfo.got;
ref.relsymbol:=current_procinfo.CurrGOTLabel;
end;
add_hreg:=true
end
end
else if (cs_create_pic in current_settings.moduleswitches) and
assigned(ref.symbol) and
not((ref.symbol.bind=AB_LOCAL) and
(ref.symbol.typ in [AT_LABEL,AT_FUNCTION])) then
begin
reference_reset_symbol(href,ref.symbol,0);
hreg:=getaddressregister(list);
href.refaddr:=addr_pic;
href.base:=current_procinfo.got;
include(current_procinfo.flags,pi_needs_got);
list.concat(taicpu.op_ref_reg(A_MOV,S_L,href,hreg));
ref.symbol:=nil;
add_hreg:=true;
end;
if add_hreg then
begin
if ref.base=NR_NO then
ref.base:=hreg
else if ref.index=NR_NO then
@ -770,7 +800,29 @@ unit cgx86;
begin
if assigned(ref.symbol) then
begin
if (cs_create_pic in current_settings.moduleswitches) then
if (target_info.system=system_i386_darwin) and
((ref.symbol.bind = AB_EXTERNAL) or
(cs_create_pic in current_settings.moduleswitches)) then
begin
if (ref.symbol.bind = AB_EXTERNAL) or
((cs_create_pic in current_settings.moduleswitches) and
(ref.symbol.bind in [AB_COMMON,AB_GLOBAL])) then
begin
reference_reset_base(tmpref,
g_indirect_sym_load(list,ref.symbol.name),
offset);
a_loadaddr_ref_reg(list,tmpref,r);
end
else
begin
include(current_procinfo.flags,pi_needs_got);
reference_reset_base(tmpref,current_procinfo.got,offset);
tmpref.symbol:=symbol;
tmpref.relsymbol:=current_procinfo.CurrGOTLabel;
list.concat(Taicpu.op_ref_reg(A_LEA,tcgsize2opsize[OS_ADDR],tmpref,r));
end;
end
else if (cs_create_pic in current_settings.moduleswitches) then
begin
{$ifdef x86_64}
reference_reset_symbol(tmpref,ref.symbol,0);
@ -1996,7 +2048,13 @@ unit cgx86;
got loaded
}
g_maybe_got_init(list);
ref.refaddr:=addr_pic;
if (target_info.system<>system_i386_darwin) then
ref.refaddr:=addr_pic
else
begin
ref.refaddr:=addr_no;
ref.relsymbol:=current_procinfo.CurrGOTLabel;
end
end
else
ref.refaddr:=addr_full;