mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-07 21:26:57 +02:00
* MIPS: fixed parameter management to properly align records smaller than 32 bits on big-endian targets.
* Also changed parameter management to allocate a single LOC_REFERENCE location for any parameter (or part of a parameter) passed on stack. Such locations can now be handled by generic code. As a consequence, TGMIPS.a_load_const_cgpara and a_load_ref_cgpara methods are no longer necessary (moreover they were ignoring parameter shifting). * a_loadfpu_ref_cgpara patched to handle 64-bit location, which are now possible. * This change eliminates code generation madness where each word of a record was copied individually, thus passing by value a 32K-word sized record was bloating into 64K instructions, multiply this number by 2 for larger records due to limited immediate offsets, and by another 2 for global record in PIC mode :/ git-svn-id: trunk@23575 -
This commit is contained in:
parent
c6c67dc182
commit
d82387ff72
@ -49,8 +49,6 @@ type
|
|||||||
procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
|
procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
|
||||||
|
|
||||||
{ parameter }
|
{ parameter }
|
||||||
procedure a_load_const_cgpara(list: tasmlist; size: tcgsize; a: tcgint; const paraloc: TCGPara); override;
|
|
||||||
procedure a_load_ref_cgpara(list: tasmlist; sz: tcgsize; const r: TReference; const paraloc: TCGPara); override;
|
|
||||||
procedure a_loadaddr_ref_cgpara(list: tasmlist; const r: TReference; const paraloc: TCGPara); override;
|
procedure a_loadaddr_ref_cgpara(list: tasmlist; const r: TReference; const paraloc: TCGPara); override;
|
||||||
procedure a_loadfpu_reg_cgpara(list: tasmlist; size: tcgsize; const r: tregister; const paraloc: TCGPara); override;
|
procedure a_loadfpu_reg_cgpara(list: tasmlist; size: tcgsize; const r: tregister; const paraloc: TCGPara); override;
|
||||||
procedure a_loadfpu_ref_cgpara(list: tasmlist; size: tcgsize; const ref: treference; const paraloc: TCGPara); override;
|
procedure a_loadfpu_ref_cgpara(list: tasmlist; size: tcgsize; const ref: treference; const paraloc: TCGPara); override;
|
||||||
@ -543,60 +541,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TCGMIPS.a_load_const_cgpara(list: tasmlist; size: tcgsize; a: tcgint; const paraloc: TCGPara);
|
|
||||||
var
|
|
||||||
Ref: TReference;
|
|
||||||
begin
|
|
||||||
paraloc.check_simple_location;
|
|
||||||
paramanager.allocparaloc(list,paraloc.location);
|
|
||||||
case paraloc.location^.loc of
|
|
||||||
LOC_REGISTER, LOC_CREGISTER:
|
|
||||||
a_load_const_reg(list, size, a, paraloc.location^.Register);
|
|
||||||
LOC_REFERENCE:
|
|
||||||
begin
|
|
||||||
with paraloc.location^.Reference do
|
|
||||||
begin
|
|
||||||
if (Index = NR_SP) and (Offset < 0) then
|
|
||||||
InternalError(2002081104);
|
|
||||||
reference_reset_base(ref, index, offset, sizeof(aint));
|
|
||||||
end;
|
|
||||||
a_load_const_ref(list, size, a, ref);
|
|
||||||
end;
|
|
||||||
else
|
|
||||||
InternalError(2002122200);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure TCGMIPS.a_load_ref_cgpara(list: tasmlist; sz: TCgSize; const r: TReference; const paraloc: TCGPara);
|
|
||||||
var
|
|
||||||
href, href2: treference;
|
|
||||||
hloc: pcgparalocation;
|
|
||||||
begin
|
|
||||||
href := r;
|
|
||||||
hloc := paraloc.location;
|
|
||||||
while assigned(hloc) do
|
|
||||||
begin
|
|
||||||
paramanager.allocparaloc(list,hloc);
|
|
||||||
case hloc^.loc of
|
|
||||||
LOC_REGISTER,LOC_CREGISTER:
|
|
||||||
a_load_ref_reg(list, hloc^.size, hloc^.size, href, hloc^.Register);
|
|
||||||
LOC_FPUREGISTER,LOC_CFPUREGISTER :
|
|
||||||
a_loadfpu_ref_reg(list,hloc^.size,hloc^.size,href,hloc^.register);
|
|
||||||
LOC_REFERENCE:
|
|
||||||
begin
|
|
||||||
reference_reset_base(href2, hloc^.reference.index, hloc^.reference.offset, sizeof(aint));
|
|
||||||
a_load_ref_ref(list, hloc^.size, hloc^.size, href, href2);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
internalerror(200408241);
|
|
||||||
end;
|
|
||||||
Inc(href.offset, tcgsize2size[hloc^.size]);
|
|
||||||
hloc := hloc^.Next;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure TCGMIPS.a_loadaddr_ref_cgpara(list: tasmlist; const r: TReference; const paraloc: TCGPara);
|
procedure TCGMIPS.a_loadaddr_ref_cgpara(list: tasmlist; const r: TReference; const paraloc: TCGPara);
|
||||||
var
|
var
|
||||||
Ref: TReference;
|
Ref: TReference;
|
||||||
@ -630,6 +574,9 @@ var
|
|||||||
href, href2: treference;
|
href, href2: treference;
|
||||||
hloc: pcgparalocation;
|
hloc: pcgparalocation;
|
||||||
begin
|
begin
|
||||||
|
{ TODO: inherited cannot deal with individual locations for each of OS_32 registers.
|
||||||
|
Must change parameter management to allocate a single 64-bit register pair,
|
||||||
|
then this method can be removed. }
|
||||||
href := ref;
|
href := ref;
|
||||||
hloc := paraloc.location;
|
hloc := paraloc.location;
|
||||||
while assigned(hloc) do
|
while assigned(hloc) do
|
||||||
@ -642,8 +589,10 @@ begin
|
|||||||
a_loadfpu_ref_reg(list,hloc^.size,hloc^.size,href,hloc^.register);
|
a_loadfpu_ref_reg(list,hloc^.size,hloc^.size,href,hloc^.register);
|
||||||
LOC_REFERENCE:
|
LOC_REFERENCE:
|
||||||
begin
|
begin
|
||||||
reference_reset_base(href2, hloc^.reference.index, hloc^.reference.offset, sizeof(aint));
|
paraloc.check_simple_location;
|
||||||
a_load_ref_ref(list, hloc^.size, hloc^.size, href, href2);
|
reference_reset_base(href2,paraloc.location^.reference.index,paraloc.location^.reference.offset,paraloc.alignment);
|
||||||
|
{ concatcopy should choose the best way to copy the data }
|
||||||
|
g_concatcopy(list,ref,href2,tcgsize2size[size]);
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
internalerror(200408241);
|
internalerror(200408241);
|
||||||
|
@ -384,6 +384,17 @@ implementation
|
|||||||
paraloc^.size:=OS_32
|
paraloc^.size:=OS_32
|
||||||
else
|
else
|
||||||
paraloc^.size:=paracgsize;
|
paraloc^.size:=paracgsize;
|
||||||
|
|
||||||
|
{ big-endian targets require that record data stored in parameter
|
||||||
|
registers is left-aligned }
|
||||||
|
if (target_info.endian=endian_big) and
|
||||||
|
(paradef.typ = recorddef) and
|
||||||
|
(tcgsize2size[paraloc^.size] <> sizeof(aint)) then
|
||||||
|
begin
|
||||||
|
paraloc^.shiftval := (sizeof(aint)-tcgsize2size[paraloc^.size])*(-8);
|
||||||
|
paraloc^.size := OS_INT;
|
||||||
|
end;
|
||||||
|
|
||||||
{ ret in param? }
|
{ ret in param? }
|
||||||
if (vo_is_funcret in hp.varoptions) and
|
if (vo_is_funcret in hp.varoptions) and
|
||||||
is_abi_record(hp.vardef) then
|
is_abi_record(hp.vardef) then
|
||||||
@ -393,7 +404,7 @@ implementation
|
|||||||
begin
|
begin
|
||||||
TMIPSProcInfo(current_procinfo).register_used[0]:=true;
|
TMIPSProcInfo(current_procinfo).register_used[0]:=true;
|
||||||
TMIPSProcInfo(current_procinfo).register_name[0]:='result';
|
TMIPSProcInfo(current_procinfo).register_name[0]:='result';
|
||||||
TMIPSProcInfo(current_procinfo).register_size[0]:=paracgsize;
|
TMIPSProcInfo(current_procinfo).register_size[0]:=paraloc^.size;
|
||||||
TMIPSProcInfo(current_procinfo).register_offset[0]:=0;
|
TMIPSProcInfo(current_procinfo).register_offset[0]:=0;
|
||||||
end;
|
end;
|
||||||
//if (intparareg<>1) then
|
//if (intparareg<>1) then
|
||||||
@ -453,7 +464,7 @@ implementation
|
|||||||
begin
|
begin
|
||||||
TMIPSProcInfo(current_procinfo).register_used[intparareg]:=true;
|
TMIPSProcInfo(current_procinfo).register_used[intparareg]:=true;
|
||||||
TMIPSProcInfo(current_procinfo).register_name[intparareg]:=hp.prettyname;
|
TMIPSProcInfo(current_procinfo).register_name[intparareg]:=hp.prettyname;
|
||||||
TMIPSProcInfo(current_procinfo).register_size[intparareg]:=paracgsize;
|
TMIPSProcInfo(current_procinfo).register_size[intparareg]:=paraloc^.size;
|
||||||
TMIPSProcInfo(current_procinfo).register_offset[intparareg]:=intparareg*mips_sizeof_register_param;
|
TMIPSProcInfo(current_procinfo).register_offset[intparareg]:=intparareg*mips_sizeof_register_param;
|
||||||
end;
|
end;
|
||||||
if side=callerside then
|
if side=callerside then
|
||||||
@ -481,14 +492,18 @@ implementation
|
|||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
paraloc^.loc:=LOC_REFERENCE;
|
paraloc^.loc:=LOC_REFERENCE;
|
||||||
|
paraloc^.size:=int_cgsize(paralen);
|
||||||
|
|
||||||
{ Force size to multiple of 4 for records passed by value,
|
{ Force size to multiple of 4 for records passed by value,
|
||||||
to obtain correct memory layout for big endian }
|
to obtain correct memory layout for big endian }
|
||||||
|
(*
|
||||||
if (paradef.typ = recorddef) and
|
if (paradef.typ = recorddef) and
|
||||||
(tcgsize2size[paraloc^.size] < tcgsize2size[OS_32]) then
|
(tcgsize2size[paraloc^.size] < tcgsize2size[OS_32]) then
|
||||||
begin
|
begin
|
||||||
inc(paralen,tcgsize2size[OS_32]-tcgsize2size[paraloc^.size]);
|
inc(paralen,tcgsize2size[OS_32]-tcgsize2size[paraloc^.size]);
|
||||||
paraloc^.size := OS_32;
|
paraloc^.size := OS_32;
|
||||||
end;
|
end;
|
||||||
|
*)
|
||||||
if side=callerside then
|
if side=callerside then
|
||||||
begin
|
begin
|
||||||
paraloc^.reference.index := NR_STACK_POINTER_REG;
|
paraloc^.reference.index := NR_STACK_POINTER_REG;
|
||||||
@ -506,7 +521,8 @@ implementation
|
|||||||
end;
|
end;
|
||||||
paraloc^.reference.offset:=intparasize;
|
paraloc^.reference.offset:=intparasize;
|
||||||
end;
|
end;
|
||||||
inc(intparasize,align(tcgsize2size[paraloc^.size],mips_sizeof_register_param));
|
inc(intparasize,align(paralen,mips_sizeof_register_param));
|
||||||
|
paralen:=0;
|
||||||
end;
|
end;
|
||||||
dec(paralen,tcgsize2size[paraloc^.size]);
|
dec(paralen,tcgsize2size[paraloc^.size]);
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user