+ basic support for pic on arm-linux

git-svn-id: trunk@25297 -
This commit is contained in:
florian 2013-08-19 21:35:37 +00:00
parent 7ac3647ff2
commit 6606955b88
6 changed files with 113 additions and 14 deletions

View File

@ -140,7 +140,8 @@ interface
aitconst_32bit_unaligned,
aitconst_64bit_unaligned,
{ i8086 far pointer; emits: 'DW symbol, SEG symbol' }
aitconst_farptr
aitconst_farptr,
aitconst_got
);
const
@ -572,7 +573,9 @@ interface
constructor Create_sym(_sym:tasmsymbol);
constructor Create_type_sym(_typ:taiconst_type;_sym:tasmsymbol);
constructor Create_sym_offset(_sym:tasmsymbol;ofs:aint);
constructor Create_type_sym_offset(_typ:taiconst_type;_sym:tasmsymbol;ofs:aint);
constructor Create_rel_sym(_typ:taiconst_type;_sym,_endsym:tasmsymbol);
constructor Create_rel_sym_offset(_typ : taiconst_type; _sym,_endsym : tasmsymbol; _ofs : int64);
constructor Create_rva_sym(_sym:tasmsymbol);
constructor Createname(const name:string;ofs:aint);
constructor Createname(const name:string;_symtyp:Tasmsymtype;ofs:aint);
@ -1684,6 +1687,24 @@ implementation
end;
constructor tai_const.Create_type_sym_offset(_typ : taiconst_type;_sym : tasmsymbol; ofs : aint);
begin
inherited Create;
typ:=ait_const;
consttype:=_typ;
{ sym is allowed to be nil, this is used to write nil pointers }
sym:=_sym;
endsym:=nil;
{ store the original offset in symofs so that we can recalculate the
value field in the assembler }
symofs:=ofs;
value:=ofs;
{ update sym info }
if assigned(sym) then
sym.increfs;
end;
constructor tai_const.Create_rel_sym(_typ:taiconst_type;_sym,_endsym:tasmsymbol);
begin
self.create_sym_offset(_sym,0);
@ -1693,6 +1714,15 @@ implementation
end;
constructor tai_const.Create_rel_sym_offset(_typ: taiconst_type; _sym,_endsym: tasmsymbol; _ofs: int64);
begin
self.create_sym_offset(_sym,_ofs);
consttype:=_typ;
endsym:=_endsym;
endsym.increfs;
end;
constructor tai_const.Create_rva_sym(_sym:tasmsymbol);
begin
self.create_sym_offset(_sym,0);

View File

@ -956,6 +956,11 @@ implementation
AsmLn;
end;
{$endif cpu64bitaddr}
aitconst_got:
begin
AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(GOT)');
Asmln;
end;
aitconst_uleb128bit,
aitconst_sleb128bit,
{$ifdef cpu64bitaddr}

View File

@ -164,10 +164,10 @@ unit agarmgas;
if (base<>NR_NO) and not(is_pc(base)) then
internalerror(200309011);
s:=symbol.name;
if offset<0 then
s:=s+tostr(offset)
else if offset>0 then
s:=s+'+'+tostr(offset);
if offset<>0 then
s:=s+tostr_with_plus(offset);
if refaddr=addr_pic then
s:=s+'(PLT)';
end
else
begin

View File

@ -74,6 +74,7 @@ unit cgcpu;
procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
procedure g_maybe_got_init(list : TAsmList); override;
procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
@ -624,6 +625,8 @@ unit cgcpu;
procedure tbasecgarm.a_call_name(list : TAsmList;const s : string; weak: boolean);
var
branchopcode: tasmop;
r : treference;
sym : TAsmSymbol;
begin
{ check not really correct: should only be used for non-Thumb cpus }
if CPUARM_HAS_BLX_LABEL in cpu_capabilities[current_settings.cputype] then
@ -631,10 +634,23 @@ unit cgcpu;
else
branchopcode:=A_BL;
if target_info.system<>system_arm_darwin then
if not weak then
list.concat(taicpu.op_sym(branchopcode,current_asmdata.RefAsmSymbol(s)))
else
list.concat(taicpu.op_sym(branchopcode,current_asmdata.WeakRefAsmSymbol(s)))
begin
if not(weak) then
sym:=current_asmdata.RefAsmSymbol(s)
else
sym:=current_asmdata.WeakRefAsmSymbol(s);
reference_reset_symbol(r,sym,0,sizeof(pint));
if cs_create_pic in current_settings.moduleswitches then
begin
include(current_procinfo.flags,pi_needs_got);
r.refaddr:=addr_pic
end
else
r.refaddr:=addr_full;
list.concat(taicpu.op_ref(branchopcode,r));
end
else
list.concat(taicpu.op_sym(branchopcode,get_darwin_call_stub(s,weak)));
{
@ -2104,6 +2120,29 @@ unit cgcpu;
end;
procedure tbasecgarm.g_maybe_got_init(list : TAsmList);
var
ref : treference;
l : TAsmLabel;
begin
if (cs_create_pic in current_settings.moduleswitches) and
(pi_needs_got in current_procinfo.flags) then
begin
reference_reset(ref,4);
current_asmdata.getdatalabel(l);
cg.a_label(current_procinfo.aktlocaldata,l);
ref.symbol:=l;
ref.base:=NR_PC;
ref.symboldata:=current_procinfo.aktlocaldata.last;
list.concat(Taicpu.op_reg_ref(A_LDR,current_procinfo.got,ref));
current_asmdata.getaddrlabel(l);
current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_32bit,l,current_asmdata.RefAsmSymbol('_GLOBAL_OFFSET_TABLE_'),-8));
cg.a_label(list,l);
list.concat(Taicpu.op_reg_reg_reg(A_ADD,current_procinfo.got,NR_PC,current_procinfo.got));
end;
end;
procedure tbasecgarm.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
var
b : byte;
@ -2197,7 +2236,11 @@ unit cgcpu;
indirection_done:=true;
end
else
current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset))
if (cs_create_pic in current_settings.moduleswitches) and
(tf_pic_uses_got in target_info.flags) then
current_procinfo.aktlocaldata.concat(tai_const.Create_type_sym_offset(aitconst_got,ref.symbol,ref.offset))
else
current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset))
end
else
current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
@ -2209,6 +2252,16 @@ unit cgcpu;
tmpref.symbol:=l;
tmpref.base:=NR_PC;
list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
if (cs_create_pic in current_settings.moduleswitches) and
(tf_pic_uses_got in target_info.flags) and
assigned(ref.symbol) then
begin
reference_reset(tmpref,4);
tmpref.base:=current_procinfo.got;
tmpref.index:=tmpreg;
list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
end;
end;
{ This routine can be called with PC as base/index in case the offset

View File

@ -29,7 +29,8 @@ unit cpupi;
uses
globtype,cutils,
procinfo,cpuinfo,psub;
procinfo,cpuinfo,psub,
aasmdata;
type
tarmprocinfo = class(tcgprocinfo)
@ -45,6 +46,7 @@ unit cpupi;
function calc_stackframe_size:longint;override;
procedure init_framepointer; override;
procedure generate_parameter_info;override;
procedure allocate_got_register(list : TAsmList);override;
end;
@ -212,6 +214,12 @@ unit cpupi;
end;
procedure tarmprocinfo.allocate_got_register(list: TAsmList);
begin
got := cg.getaddressregister(list);
end;
begin
cprocinfo:=tarmprocinfo;
end.

View File

@ -553,7 +553,8 @@ unit i_linux;
shortname : 'Linux';
flags : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
tf_requires_proper_alignment,
tf_smartlink_sections,tf_smartlink_library,tf_has_winlike_resources];
tf_smartlink_sections,tf_smartlink_library,tf_pic_uses_got,
tf_has_winlike_resources];
cpu : cpu_arm;
unit_env : 'LINUXUNITS';
extradefines : 'UNIX;HASUNIX;CPUARMHF';
@ -618,7 +619,8 @@ unit i_linux;
shortname : 'Linux';
flags : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
tf_requires_proper_alignment,
tf_smartlink_sections,tf_smartlink_library,tf_has_winlike_resources];
tf_smartlink_sections,tf_smartlink_library,tf_pic_uses_got,
tf_has_winlike_resources];
cpu : cpu_arm;
unit_env : 'LINUXUNITS';
extradefines : 'UNIX;HASUNIX;CPUARMEL';
@ -683,7 +685,8 @@ unit i_linux;
shortname : 'Linux';
flags : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
tf_requires_proper_alignment,
tf_smartlink_sections,tf_smartlink_library,tf_has_winlike_resources];
tf_smartlink_sections,tf_smartlink_library,tf_pic_uses_got,
tf_has_winlike_resources];
cpu : cpu_arm;
unit_env : 'LINUXUNITS';
extradefines : 'UNIX;HASUNIX;CPUARMEB';