Merged revision(s) 31681, 31706, 31712, 31728, 31730, 31755 from trunk (ARM PIC):

* Big fix for ARM GOT support to make it work:
  - Fixed access to symbols with offset.
  - Always use register R9 for GOT pointer to prevent bugs when free register limit is reached in a function.
  - GOT is not needed for function calls by name.
........
* Fixed instruction re-scheduler for ARM in case of PIC.
........
* ARM: Do not use R9 as a fixed GOT register.
........
* ARM: Fixed GOT init when optimization is off.
........
* ARM: I hope this is a final proper fix for GOT initialization. + Test.
........
* Removed a leftover of my code. It is not needed anymore.
........

git-svn-id: branches/fixes_3_0@33438 -
This commit is contained in:
yury 2016-04-07 13:39:41 +00:00
parent 30c1bd9125
commit 463152d34b
5 changed files with 123 additions and 10 deletions

1
.gitattributes vendored
View File

@ -10396,6 +10396,7 @@ tests/tbs/tb0608.pp svneol=native#text/pascal
tests/tbs/tb0609.pp svneol=native#text/plain tests/tbs/tb0609.pp svneol=native#text/plain
tests/tbs/tb205.pp svneol=native#text/plain tests/tbs/tb205.pp svneol=native#text/plain
tests/tbs/tb610.pp svneol=native#text/pascal tests/tbs/tb610.pp svneol=native#text/pascal
tests/tbs/tb613.pp svneol=native#text/plain
tests/tbs/tbs0594.pp svneol=native#text/pascal tests/tbs/tbs0594.pp svneol=native#text/pascal
tests/tbs/ub0060.pp svneol=native#text/plain tests/tbs/ub0060.pp svneol=native#text/plain
tests/tbs/ub0069.pp svneol=native#text/plain tests/tbs/ub0069.pp svneol=native#text/plain

View File

@ -953,6 +953,8 @@ implementation
{$endif cpu64bitaddr} {$endif cpu64bitaddr}
aitconst_got: aitconst_got:
begin begin
if tai_const(hp).symofs<>0 then
InternalError(2015091401); // No symbol offset is allowed for GOT.
AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(GOT)'); AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(GOT)');
Asmln; Asmln;
end; end;

View File

@ -2500,13 +2500,16 @@ Implementation
hp3:=tai(p.Previous); hp3:=tai(p.Previous);
hp5:=tai(p.next); hp5:=tai(p.next);
asml.Remove(p); asml.Remove(p);
{ if there is a reg. dealloc instruction associated with p, move it together with p } { if there is a reg. dealloc instruction or address labels (e.g. for GOT-less PIC)
associated with p, move it together with p }
{ before the instruction? } { before the instruction? }
while assigned(hp3) and (hp3.typ<>ait_instruction) do while assigned(hp3) and (hp3.typ<>ait_instruction) do
begin begin
if (hp3.typ=ait_regalloc) and (tai_regalloc(hp3).ratype in [ra_dealloc]) and if ( (hp3.typ=ait_regalloc) and (tai_regalloc(hp3).ratype in [ra_dealloc]) and
RegInInstruction(tai_regalloc(hp3).reg,p) then RegInInstruction(tai_regalloc(hp3).reg,p) )
or ( (hp3.typ=ait_label) and (tai_label(hp3).labsym.typ=AT_ADDR) )
then
begin begin
hp4:=hp3; hp4:=hp3;
hp3:=tai(hp3.Previous); hp3:=tai(hp3.Previous);
@ -2552,7 +2555,7 @@ Implementation
{$endif DEBUG_PREREGSCHEDULER} {$endif DEBUG_PREREGSCHEDULER}
asml.InsertBefore(hp1,insertpos); asml.InsertBefore(hp1,insertpos);
asml.InsertListBefore(insertpos,list); asml.InsertListBefore(insertpos,list);
p:=tai(p.next) p:=tai(p.next);
end end
else if p.typ=ait_instruction then else if p.typ=ait_instruction then
p:=hp1 p:=hp1

View File

@ -653,7 +653,6 @@ unit cgcpu;
if (tf_pic_uses_got in target_info.flags) and if (tf_pic_uses_got in target_info.flags) and
(cs_create_pic in current_settings.moduleswitches) then (cs_create_pic in current_settings.moduleswitches) then
begin begin
include(current_procinfo.flags,pi_needs_got);
r.refaddr:=addr_pic r.refaddr:=addr_pic
end end
else else
@ -2263,22 +2262,43 @@ unit cgcpu;
var var
ref : treference; ref : treference;
l : TAsmLabel; l : TAsmLabel;
regs : tcpuregisterset;
r: byte;
begin begin
if (cs_create_pic in current_settings.moduleswitches) and if (cs_create_pic in current_settings.moduleswitches) and
(pi_needs_got in current_procinfo.flags) and (pi_needs_got in current_procinfo.flags) and
(tf_pic_uses_got in target_info.flags) then (tf_pic_uses_got in target_info.flags) then
begin begin
{ Procedure parametrs are not initialized at this stage.
Before GOT initialization code, allocate registers used for procedure parameters
to prevent usage of these registers for temp operations in later stages of code
generation. }
regs:=rg[R_INTREGISTER].used_in_proc;
for r:=RS_R0 to RS_R3 do
if r in regs then
a_reg_alloc(list, newreg(R_INTREGISTER,r,R_SUBWHOLE));
{ Allocate scratch register R12 and use it for GOT calculations directly.
Otherwise the init code can be distorted in later stages of code generation. }
a_reg_alloc(list,NR_R12);
reference_reset(ref,4); reference_reset(ref,4);
current_asmdata.getdatalabel(l); current_asmdata.getdatalabel(l);
cg.a_label(current_procinfo.aktlocaldata,l); cg.a_label(current_procinfo.aktlocaldata,l);
ref.symbol:=l; ref.symbol:=l;
ref.base:=NR_PC; ref.base:=NR_PC;
ref.symboldata:=current_procinfo.aktlocaldata.last; ref.symboldata:=current_procinfo.aktlocaldata.last;
list.concat(Taicpu.op_reg_ref(A_LDR,current_procinfo.got,ref)); list.concat(Taicpu.op_reg_ref(A_LDR,NR_R12,ref));
current_asmdata.getaddrlabel(l); current_asmdata.getaddrlabel(l);
current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_32bit,l,current_asmdata.RefAsmSymbol('_GLOBAL_OFFSET_TABLE_'),-8)); 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); cg.a_label(list,l);
list.concat(Taicpu.op_reg_reg_reg(A_ADD,current_procinfo.got,NR_PC,current_procinfo.got)); list.concat(Taicpu.op_reg_reg_reg(A_ADD,NR_R12,NR_PC,NR_R12));
list.concat(Taicpu.op_reg_reg(A_MOV,current_procinfo.got,NR_R12));
{ Deallocate registers }
a_reg_dealloc(list,NR_R12);
for r:=RS_R3 downto RS_R0 do
if r in regs then
a_reg_dealloc(list, newreg(R_INTREGISTER,r,R_SUBWHOLE));
end; end;
end; end;
@ -2374,12 +2394,12 @@ unit cgcpu;
begin begin
tmpreg:=g_indirect_sym_load(list,ref.symbol.name,asmsym2indsymflags(ref.symbol)); tmpreg:=g_indirect_sym_load(list,ref.symbol.name,asmsym2indsymflags(ref.symbol));
if ref.offset<>0 then if ref.offset<>0 then
a_op_const_reg(list,OP_ADD,OS_ADDR,ref.offset,tmpreg); a_op_const_reg(list,OP_ADD,OS_ADDR,ref.offset,tmpreg);
indirection_done:=true; indirection_done:=true;
end end
else if (cs_create_pic in current_settings.moduleswitches) then else if (cs_create_pic in current_settings.moduleswitches) then
if (tf_pic_uses_got in target_info.flags) then if (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)) current_procinfo.aktlocaldata.concat(tai_const.Create_type_sym(aitconst_got,ref.symbol))
else else
begin begin
{ ideally, we would want to generate { ideally, we would want to generate
@ -2403,7 +2423,7 @@ unit cgcpu;
current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset)) current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset))
end end
else else
current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset)); current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
{ load consts entry } { load consts entry }
if not indirection_done then if not indirection_done then
@ -2421,6 +2441,8 @@ unit cgcpu;
tmpref.base:=current_procinfo.got; tmpref.base:=current_procinfo.got;
tmpref.index:=tmpreg; tmpref.index:=tmpreg;
list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref)); list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
if ref.offset<>0 then
a_op_const_reg(list,OP_ADD,OS_ADDR,ref.offset,tmpreg);
end; end;
end; end;

85
tests/tbs/tb613.pp Normal file
View File

@ -0,0 +1,85 @@
{$mode objfpc}
{$PIC+}
{
Test for proper initialization of GOT register.
}
const
BufSize = 128*1024;
var
gvar: longint;
procedure check(c, e: longint);
begin
if c <> e then begin
writeln('ERROR. Result: ', c, ' Expected: ', e);
Halt(1);
end;
end;
function test101(p1, p2: longint): longint;
begin
result:=gvar+p1+p2;
end;
function test102(p1, p2: longint): longint;
var
Buffer: array[0..BufSize] of byte;
begin
Buffer[0]:=0;
result:=gvar+p1+p2+Buffer[0];
end;
function test103(p1, p2: longint): longint;
var
a, j: longint;
begin
a:=0;
for j:=1 to 1 do begin
a:=a + j;
a:=a - j;
end;
result:=gvar+p1+p2+a;
end;
function test111(p1, p2: longint): longint;
var
i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15: longint;
a, j: longint;
begin
i1:=1;i2:=2;i3:=3;i4:=4;i5:=5;i6:=6;i7:=7;i8:=8;i9:=9;i10:=10;i11:=11;i12:=12;i13:=13;i14:=14;i15:=15;
a:=0;
for j:=1 to 1 do begin
a:=a + (i1+i2+i3+i4+i5+i6+i7+i8+i9+i10+i11+i12+i13+i14+i15);
a:=a - (i1+i2+i3+i4+i5+i6+i7+i8+i9+i10+i11+i12+i13+i14+i15);
end;
result:=gvar+p1+p2+a;
end;
function test112(p1, p2: longint): longint;
var
i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15: longint;
a, j: longint;
Buffer: array[0..BufSize] of byte;
begin
i1:=1;i2:=2;i3:=3;i4:=4;i5:=5;i6:=6;i7:=7;i8:=8;i9:=9;i10:=10;i11:=11;i12:=12;i13:=13;i14:=14;i15:=15;
a:=0;
Buffer[0]:=0;
for j:=1 to 1 do begin
a:=a + (i1+i2+i3+i4+i5+i6+i7+i8+i9+i10+i11+i12+i13+i14+i15);
a:=a - (i1+i2+i3+i4+i5+i6+i7+i8+i9+i10+i11+i12+i13+i14+i15);
a:=a + Buffer[0];
end;
result:=gvar+p1+p2+a;
end;
begin
gvar:=100;
check(test101(10, 20), 130);
check(test102(20, 30), 150);
check(test103(30, 40), 170);
check(test111(110, 20), 230);
check(test112(120, 30), 250);
end.