summaryrefslogtreecommitdiff
path: root/compiler/arm/cpupara.pas
diff options
context:
space:
mode:
authorjonas <jonas@3ad0048d-3df7-0310-abae-a5850022a9f2>2010-05-30 21:12:57 +0000
committerjonas <jonas@3ad0048d-3df7-0310-abae-a5850022a9f2>2010-05-30 21:12:57 +0000
commit585c02b95e1e192a626d9a56a97a5acc27b4c1c3 (patch)
tree0c5eb1ec8cdc5b860f11ea21b0d9b1a525efc0f8 /compiler/arm/cpupara.pas
parente0d417123e477a6c50ff67c1c7ae13212279a102 (diff)
downloadfpc-585c02b95e1e192a626d9a56a97a5acc27b4c1c3.tar.gz
* changed tprocdef.funcretloc[] from a tlocation into a tcgpara so it can
represent complex locations (required for full x86-64 ABI support, which is not yet implemented) -> lots of special result handling code has been removed and replaced by the parameter handling routines + added support for composite parameters (and hence function results) to tcg.a_load_ref_cgpara() (so it can be used for handling, e.g., 64 bit parameters on 32 bit platforms) * the above fixed writing past the end of allocated memory when handling records returned in registers on x86-64 whose size is not a multiple of 8 bytes (mantis #16357) - removed the x86-64 and PPC specific versions of a_load_ref_cgpara(), as they are now handled correctly by the generic version * moved the responsibility of allocating tcgpara cpu registers (using paramanager.allocparaloc()) from the callers of cg.a_load*_cgpara() to the cg.a_load*_cgpara() methods themselves (so the register allocation can be done efficiently when dealing with function results) * for the above, renamed paramanager.alloc/freeparaloc() to paramanager.alloc/freecgpara(), and use paramanager.allocparaloc() to allocate individual pcgparalocations instead * fixed the register size of SSE2 function result registers for x86-64 (when used for floating point), which results in removing a few superfluous "movs? %xmm0,%xmm0" instructions * fixed compilation of paramanagers of avr, m68k and mips after r13695 and also updated them for these new changes git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@15350 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'compiler/arm/cpupara.pas')
-rw-r--r--compiler/arm/cpupara.pas80
1 files changed, 50 insertions, 30 deletions
diff --git a/compiler/arm/cpupara.pas b/compiler/arm/cpupara.pas
index 367ca94738..0f0b9d71ad 100644
--- a/compiler/arm/cpupara.pas
+++ b/compiler/arm/cpupara.pas
@@ -42,7 +42,7 @@ unit cpupara;
procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
- function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;override;
+ function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;override;
private
procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
@@ -451,32 +451,45 @@ unit cpupara;
end;
- function tarmparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;
+ function tarmparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;
var
+ paraloc : pcgparalocation;
retcgsize : tcgsize;
begin
- { Constructors return self instead of a boolean }
- if (p.proctypeoption=potype_constructor) then
- retcgsize:=OS_ADDR
- else
- retcgsize:=def_cgsize(def);
-
- location_reset(result,LOC_INVALID,OS_NO);
- result.size:=retcgsize;
-
+ result.init;
+ result.alignment:=get_para_align(p.proccalloption);
{ void has no location }
if is_void(def) then
begin
- location_reset(result,LOC_VOID,OS_NO);
+ paraloc:=result.add_location;
+ result.size:=OS_NO;
+ result.intsize:=0;
+ paraloc^.size:=OS_NO;
+ paraloc^.loc:=LOC_VOID;
exit;
end;
+ { Constructors return self instead of a boolean }
+ if (p.proctypeoption=potype_constructor) then
+ begin
+ retcgsize:=OS_ADDR;
+ result.intsize:=sizeof(pint);
+ end
+ else
+ begin
+ retcgsize:=def_cgsize(def);
+ result.intsize:=def.size;
+ end;
+ result.size:=retcgsize;
{ Return is passed as var parameter }
if ret_in_param(def,p.proccalloption) then
begin
- result.loc:=LOC_REFERENCE;
- result.size:=retcgsize;
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=retcgsize;
exit;
end;
+
+ paraloc:=result.add_location;
{ Return in FPU register? }
if def.typ=floatdef then
begin
@@ -488,18 +501,20 @@ unit cpupara;
OS_64,
OS_F64:
begin
- { low }
- result.loc:=LOC_REGISTER;
- result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG;
- result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG;
- result.size:=OS_64;
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
+ paraloc^.size:=OS_32;
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
+ paraloc^.size:=OS_32;
end;
OS_32,
OS_F32:
begin
- result.loc:=LOC_REGISTER;
- result.register:=NR_FUNCTION_RETURN_REG;
- result.size:=OS_32;
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RETURN_REG;
+ paraloc^.size:=OS_32;
end;
else
internalerror(2005082603);
@@ -507,8 +522,9 @@ unit cpupara;
end
else
begin
- result.loc:=LOC_FPUREGISTER;
- result.register:=NR_FPU_RESULT_REG;
+ paraloc^.loc:=LOC_FPUREGISTER;
+ paraloc^.register:=NR_FPU_RESULT_REG;
+ paraloc^.size:=retcgsize;
end;
end
{ Return in register }
@@ -516,15 +532,19 @@ unit cpupara;
begin
if retcgsize in [OS_64,OS_S64] then
begin
- { low }
- result.loc:=LOC_REGISTER;
- result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG;
- result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG;
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
+ paraloc^.size:=OS_32;
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
+ paraloc^.size:=OS_32;
end
else
begin
- result.loc:=LOC_REGISTER;
- result.register:=NR_FUNCTION_RETURN_REG;
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RETURN_REG;
+ paraloc^.size:=retcgsize;
end;
end;
end;