mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 08:48:08 +02:00
* ARM: I hope this is a final proper fix for GOT initialization. + Test.
git-svn-id: trunk@31730 -
This commit is contained in:
parent
fc6837799e
commit
80e5eb0c5d
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||
|
@ -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
85
tests/tbs/tb613.pp
Normal 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.
|
Loading…
Reference in New Issue
Block a user