mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-11 18:25:58 +02:00
+ LLVM temp allocator based on new R_TEMPREGISTER register class. For every
temp we allocate, we set the base register to a newly allocated R_TEMPREGISTER. This allows for uniquely identifying a temp even if its offset is modified. git-svn-id: branches/hlcgllvm@26033 -
This commit is contained in:
parent
9573160c1a
commit
1df3039424
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -314,6 +314,7 @@ compiler/jvm/rjvmsup.inc svneol=native#text/plain
|
|||||||
compiler/jvm/tgcpu.pas svneol=native#text/plain
|
compiler/jvm/tgcpu.pas svneol=native#text/plain
|
||||||
compiler/ldscript.pas svneol=native#text/plain
|
compiler/ldscript.pas svneol=native#text/plain
|
||||||
compiler/link.pas svneol=native#text/plain
|
compiler/link.pas svneol=native#text/plain
|
||||||
|
compiler/llvm/tgllvm.pas svneol=native#text/plain
|
||||||
compiler/m68k/aasmcpu.pas svneol=native#text/plain
|
compiler/m68k/aasmcpu.pas svneol=native#text/plain
|
||||||
compiler/m68k/ag68kgas.pas svneol=native#text/plain
|
compiler/m68k/ag68kgas.pas svneol=native#text/plain
|
||||||
compiler/m68k/aoptcpu.pas svneol=native#text/plain
|
compiler/m68k/aoptcpu.pas svneol=native#text/plain
|
||||||
|
@ -171,7 +171,9 @@ interface
|
|||||||
R_MMXREGISTER, { = 3 }
|
R_MMXREGISTER, { = 3 }
|
||||||
R_MMREGISTER, { = 4 }
|
R_MMREGISTER, { = 4 }
|
||||||
R_SPECIALREGISTER, { = 5 }
|
R_SPECIALREGISTER, { = 5 }
|
||||||
R_ADDRESSREGISTER { = 6 }
|
R_ADDRESSREGISTER, { = 6 }
|
||||||
|
{ used on llvm, every temp gets its own "base register" }
|
||||||
|
R_TEMPREGISTER { = 7 }
|
||||||
);
|
);
|
||||||
|
|
||||||
{ Sub registers }
|
{ Sub registers }
|
||||||
|
@ -85,6 +85,7 @@ unit cgobj;
|
|||||||
function getfpuregister(list:TAsmList;size:Tcgsize):Tregister;virtual;
|
function getfpuregister(list:TAsmList;size:Tcgsize):Tregister;virtual;
|
||||||
function getmmregister(list:TAsmList;size:Tcgsize):Tregister;virtual;
|
function getmmregister(list:TAsmList;size:Tcgsize):Tregister;virtual;
|
||||||
function getflagregister(list:TAsmList;size:Tcgsize):Tregister;virtual;
|
function getflagregister(list:TAsmList;size:Tcgsize):Tregister;virtual;
|
||||||
|
function gettempregister(list:TAsmList):Tregister;virtual;
|
||||||
{Does the generic cg need SIMD registers, like getmmxregister? Or should
|
{Does the generic cg need SIMD registers, like getmmxregister? Or should
|
||||||
the cpu specific child cg object have such a method?}
|
the cpu specific child cg object have such a method?}
|
||||||
|
|
||||||
@ -661,6 +662,12 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function tcg.gettempregister(list: TAsmList): Tregister;
|
||||||
|
begin
|
||||||
|
result:=rg[R_TEMPREGISTER].getregister(list,R_SUBWHOLE);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function Tcg.makeregsize(list:TAsmList;reg:Tregister;size:Tcgsize):Tregister;
|
function Tcg.makeregsize(list:TAsmList;reg:Tregister;size:Tcgsize):Tregister;
|
||||||
var
|
var
|
||||||
subreg:Tsubregister;
|
subreg:Tsubregister;
|
||||||
|
@ -72,6 +72,7 @@ unit hlcgobj;
|
|||||||
{ warning: only works correctly for fpu types currently }
|
{ warning: only works correctly for fpu types currently }
|
||||||
function getmmregister(list:TAsmList;size:tdef):Tregister;virtual;
|
function getmmregister(list:TAsmList;size:tdef):Tregister;virtual;
|
||||||
function getflagregister(list:TAsmList;size:tdef):Tregister;virtual;
|
function getflagregister(list:TAsmList;size:tdef):Tregister;virtual;
|
||||||
|
function gettempregister(list:TAsmList;size:tdef):Tregister;virtual;
|
||||||
function getregisterfordef(list: TAsmList;size:tdef):Tregister;virtual;
|
function getregisterfordef(list: TAsmList;size:tdef):Tregister;virtual;
|
||||||
{Does the generic cg need SIMD registers, like getmmxregister? Or should
|
{Does the generic cg need SIMD registers, like getmmxregister? Or should
|
||||||
the cpu specific child cg object have such a method?}
|
the cpu specific child cg object have such a method?}
|
||||||
@ -615,6 +616,13 @@ implementation
|
|||||||
result:=cg.getflagregister(list,def_cgsize(size));
|
result:=cg.getflagregister(list,def_cgsize(size));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function thlcgobj.gettempregister(list: TAsmList; size: tdef): Tregister;
|
||||||
|
begin
|
||||||
|
{ doesn't make sense to try to translate this size to tcgsize, temps
|
||||||
|
can have any size }
|
||||||
|
result:=cg.gettempregister(list);
|
||||||
|
end;
|
||||||
|
|
||||||
function thlcgobj.getregisterfordef(list: TAsmList; size: tdef): Tregister;
|
function thlcgobj.getregisterfordef(list: TAsmList; size: tdef): Tregister;
|
||||||
begin
|
begin
|
||||||
case def2regtyp(size) of
|
case def2regtyp(size) of
|
||||||
|
163
compiler/llvm/tgllvm.pas
Normal file
163
compiler/llvm/tgllvm.pas
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
{
|
||||||
|
Copyright (c) 1998-2002,2012 by Florian Klaempfl, Jonas Maebe
|
||||||
|
|
||||||
|
This unit implements the LLVM-specific temp. generator
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
****************************************************************************
|
||||||
|
}
|
||||||
|
|
||||||
|
unit tgllvm;
|
||||||
|
|
||||||
|
{$i fpcdefs.inc}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
cclasses,
|
||||||
|
globals,globtype,
|
||||||
|
symtype,
|
||||||
|
cpubase,cpuinfo,cgbase,cgutils,
|
||||||
|
aasmbase,aasmtai,aasmdata,
|
||||||
|
tgobj;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
{ LLVM temp manager: in LLVM, you allocate every temp separately using
|
||||||
|
the "alloca" instrinsic. Every such temp is a separate stack slot, but
|
||||||
|
can be turned into a regvar (or be decomposed) by LLVM. To avoid
|
||||||
|
problems with turning stack slots into regvars, we don't allocate one
|
||||||
|
big blob of memory that we manage ourselves using the regular temp
|
||||||
|
manager. Instead, we just allocate a new "stack pointer register"
|
||||||
|
(R_TEMPREGISTER) every time we need a new temp. This allows for having
|
||||||
|
the generic code generator modify the offset without interfering with
|
||||||
|
our ability to determine which temp the reference points to.
|
||||||
|
|
||||||
|
Temps are currently not reused, but that should probably be added in
|
||||||
|
the future (except if adding liveness information for the temps enables
|
||||||
|
llvm to do so by itself and we don't run out of temp registers).
|
||||||
|
}
|
||||||
|
|
||||||
|
{ ttgllvm }
|
||||||
|
|
||||||
|
ttgllvm = class(ttgobj)
|
||||||
|
protected
|
||||||
|
procedure alloctemp(list: TAsmList; size,alignment : longint; temptype : ttemptype; def:tdef; out ref: treference); override;
|
||||||
|
public
|
||||||
|
alloclist: tasmlist;
|
||||||
|
|
||||||
|
constructor create; override;
|
||||||
|
destructor destroy; override;
|
||||||
|
procedure setfirsttemp(l : longint); override;
|
||||||
|
function istemp(const ref: treference): boolean; override;
|
||||||
|
procedure getlocal(list: TAsmList; size: longint; alignment: shortint; def: tdef; var ref: treference); override;
|
||||||
|
procedure gethltemp(list: TAsmList; def: tdef; forcesize: aint; temptype: ttemptype; out ref: treference); override;
|
||||||
|
procedure gethltemptyped(list: TAsmList; def: tdef; temptype: ttemptype; out ref: treference); override;
|
||||||
|
procedure ungetiftemp(list: TAsmList; const ref: treference); override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
uses
|
||||||
|
cutils,
|
||||||
|
systems,verbose,
|
||||||
|
procinfo,
|
||||||
|
llvmbase,aasmllvm,
|
||||||
|
symconst,
|
||||||
|
cgobj
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
{ ttgllvm }
|
||||||
|
|
||||||
|
procedure ttgllvm.alloctemp(list: TAsmList; size, alignment: longint; temptype: ttemptype; def: tdef; out ref: treference);
|
||||||
|
var
|
||||||
|
tl: ptemprecord;
|
||||||
|
begin
|
||||||
|
reference_reset_base(ref,cg.gettempregister(list),0,alignment);
|
||||||
|
new(tl);
|
||||||
|
|
||||||
|
tl^.temptype:=temptype;
|
||||||
|
tl^.def:=def;
|
||||||
|
tl^.pos:=getsupreg(ref.base);
|
||||||
|
tl^.size:=size;
|
||||||
|
tl^.next:=templist;
|
||||||
|
tl^.nextfree:=nil;
|
||||||
|
templist:=tl;
|
||||||
|
list.concat(tai_tempalloc.alloc(tl^.pos,tl^.size));
|
||||||
|
{ TODO: add llvm.lifetime.start() for this allocation and afterwards
|
||||||
|
llvm.lifetime.end() for freetemp (if the llvm version supports it) }
|
||||||
|
inc(lasttemp);
|
||||||
|
{ allocation for the temp }
|
||||||
|
alloclist.concat(taillvm.op_ref_size(la_alloca,ref,def));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function ttgllvm.istemp(const ref: treference): boolean;
|
||||||
|
begin
|
||||||
|
result:=getregtype(ref.base)=R_TEMPREGISTER;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
constructor ttgllvm.create;
|
||||||
|
begin
|
||||||
|
inherited create;
|
||||||
|
direction:=1;
|
||||||
|
alloclist:=TAsmList.create;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
destructor ttgllvm.destroy;
|
||||||
|
begin
|
||||||
|
alloclist.free;
|
||||||
|
inherited destroy;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure ttgllvm.setfirsttemp(l: longint);
|
||||||
|
begin
|
||||||
|
firsttemp:=l;
|
||||||
|
lasttemp:=l;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure ttgllvm.getlocal(list: TAsmList; size: longint; alignment: shortint; def: tdef; var ref: treference);
|
||||||
|
begin
|
||||||
|
gethltemp(list,def,size,tt_persistent,ref);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure ttgllvm.gethltemp(list: TAsmList; def: tdef; forcesize: aint; temptype: ttemptype; out ref: treference);
|
||||||
|
begin
|
||||||
|
alloctemp(list,def.size,def.alignment,temptype,def,ref);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure ttgllvm.gethltemptyped(list: TAsmList; def: tdef; temptype: ttemptype; out ref: treference);
|
||||||
|
begin
|
||||||
|
inherited gethltemptyped(list, def, temptype, ref);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure ttgllvm.ungetiftemp(list: TAsmList; const ref: treference);
|
||||||
|
begin
|
||||||
|
if istemp(ref) then
|
||||||
|
FreeTemp(list,getsupreg(ref.base),[tt_normal]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
tgobjclass:=ttgllvm;
|
||||||
|
end.
|
@ -112,7 +112,7 @@ unit tgobj;
|
|||||||
The freed space can later be reallocated and reused. If this reference
|
The freed space can later be reallocated and reused. If this reference
|
||||||
is not in the temporary memory, it is simply not freed.
|
is not in the temporary memory, it is simply not freed.
|
||||||
}
|
}
|
||||||
procedure ungetiftemp(list: TAsmList; const ref : treference);
|
procedure ungetiftemp(list: TAsmList; const ref : treference); virtual;
|
||||||
|
|
||||||
{ Allocate space for a local }
|
{ Allocate space for a local }
|
||||||
procedure getlocal(list: TAsmList; size : longint;def:tdef;var ref : treference);
|
procedure getlocal(list: TAsmList; size : longint;def:tdef;var ref : treference);
|
||||||
|
@ -1568,9 +1568,9 @@ implementation
|
|||||||
(0, 1, 2, 3, 6, 7, 5, 4);
|
(0, 1, 2, 3, 6, 7, 5, 4);
|
||||||
maxsupreg: array[tregistertype] of tsuperregister=
|
maxsupreg: array[tregistertype] of tsuperregister=
|
||||||
{$ifdef x86_64}
|
{$ifdef x86_64}
|
||||||
(0, 16, 9, 8, 16, 32, 0);
|
(0, 16, 9, 8, 16, 32, 0, 0);
|
||||||
{$else x86_64}
|
{$else x86_64}
|
||||||
(0, 8, 9, 8, 8, 32, 0);
|
(0, 8, 9, 8, 8, 32, 0, 0);
|
||||||
{$endif x86_64}
|
{$endif x86_64}
|
||||||
var
|
var
|
||||||
rs: tsuperregister;
|
rs: tsuperregister;
|
||||||
|
Loading…
Reference in New Issue
Block a user