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/tb205.pp svneol=native#text/plain
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/ub0060.pp svneol=native#text/plain
tests/tbs/ub0069.pp svneol=native#text/plain

View File

@ -953,6 +953,8 @@ implementation
{$endif cpu64bitaddr}
aitconst_got:
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)');
Asmln;
end;

View File

@ -2500,13 +2500,16 @@ Implementation
hp3:=tai(p.Previous);
hp5:=tai(p.next);
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? }
while assigned(hp3) and (hp3.typ<>ait_instruction) do
begin
if (hp3.typ=ait_regalloc) and (tai_regalloc(hp3).ratype in [ra_dealloc]) and
RegInInstruction(tai_regalloc(hp3).reg,p) then
if ( (hp3.typ=ait_regalloc) and (tai_regalloc(hp3).ratype in [ra_dealloc]) and
RegInInstruction(tai_regalloc(hp3).reg,p) )
or ( (hp3.typ=ait_label) and (tai_label(hp3).labsym.typ=AT_ADDR) )
then
begin
hp4:=hp3;
hp3:=tai(hp3.Previous);
@ -2552,7 +2555,7 @@ Implementation
{$endif DEBUG_PREREGSCHEDULER}
asml.InsertBefore(hp1,insertpos);
asml.InsertListBefore(insertpos,list);
p:=tai(p.next)
p:=tai(p.next);
end
else if p.typ=ait_instruction then
p:=hp1

View File

@ -653,7 +653,6 @@ unit cgcpu;
if (tf_pic_uses_got in target_info.flags) and
(cs_create_pic in current_settings.moduleswitches) then
begin
include(current_procinfo.flags,pi_needs_got);
r.refaddr:=addr_pic
end
else
@ -2263,22 +2262,43 @@ unit cgcpu;
var
ref : treference;
l : TAsmLabel;
regs : tcpuregisterset;
r: byte;
begin
if (cs_create_pic in current_settings.moduleswitches) and
(pi_needs_got in current_procinfo.flags) and
(tf_pic_uses_got in target_info.flags) then
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);
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));
list.concat(Taicpu.op_reg_ref(A_LDR,NR_R12,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));
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;
@ -2374,12 +2394,12 @@ unit cgcpu;
begin
tmpreg:=g_indirect_sym_load(list,ref.symbol.name,asmsym2indsymflags(ref.symbol));
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;
end
else if (cs_create_pic in current_settings.moduleswitches) 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
begin
{ 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))
end
else
current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
{ load consts entry }
if not indirection_done then
@ -2421,6 +2441,8 @@ unit cgcpu;
tmpref.base:=current_procinfo.got;
tmpref.index:=tmpreg;
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;

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.