* ARM: I hope this is a final proper fix for GOT initialization. + Test.

git-svn-id: trunk@31730 -
This commit is contained in:
yury 2015-09-17 12:18:04 +00:00
parent fc6837799e
commit 80e5eb0c5d
3 changed files with 105 additions and 7 deletions

1
.gitattributes vendored
View File

@ -10754,6 +10754,7 @@ tests/tbs/tb0611.pp svneol=native#text/pascal
tests/tbs/tb0612.pp svneol=native#text/pascal
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

@ -2339,31 +2339,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.getglobaldatalabel(l);
cg.a_label(current_procinfo.aktlocaldata,l);
ref.symbol:=l;
ref.base:=NR_PC;
ref.symboldata:=current_procinfo.aktlocaldata.last;
a_reg_alloc(list,NR_R12);
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);
{
It is needed to perform GOT calculations using the scratch register R12
and then MOV the result to the GOT register. Otherwise the register allocator will use
register R0 as temp to perform calculations in case if a procedure uses all available registers.
It leads to corruption of R0 which is normally holds a value of the first procedure parameter.
}
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;

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.