+ tllvmexceptionstatehandler that emits LLVM landingpad instructions to be

referred by invoke instructions in exception catching blocks
   o for now we won't actually use ABI-compliant exception handling, but we
     need invoke/landingpad combinations for LLVM's control flow analyses to
     correctly handle code involving exception handling

git-svn-id: branches/debug_eh@40401 -
This commit is contained in:
Jonas Maebe 2018-11-29 21:30:46 +00:00
parent 3cfad8fba8
commit b6efcb9105
4 changed files with 172 additions and 4 deletions

1
.gitattributes vendored
View File

@ -343,6 +343,7 @@ compiler/llvm/llvmdef.pas svneol=native#text/plain
compiler/llvm/llvminfo.pas svneol=native#text/plain
compiler/llvm/llvmnode.pas svneol=native#text/plain
compiler/llvm/llvmpara.pas svneol=native#text/plain
compiler/llvm/llvmpi.pas svneol=native#text/plain
compiler/llvm/llvmsym.pas svneol=native#text/plain
compiler/llvm/llvmtarg.pas svneol=native#text/plain
compiler/llvm/llvmtype.pas svneol=native#text/plain

View File

@ -39,7 +39,7 @@ implementation
tgllvm,hlcgllvm,
nllvmadd,nllvmbas,nllvmcal,nllvmcnv,nllvmcon,nllvmflw,nllvminl,nllvmld,
nllvmmat,nllvmmem,nllvmtcon,nllvmutil,
llvmpara,
llvmpara,llvmpi,
symllvm;
end.

93
compiler/llvm/llvmpi.pas Normal file
View File

@ -0,0 +1,93 @@
{
Copyright (c) 2016 by Jonas Maebe
Information about the current procedure that is being compiled
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 llvmpi;
{$i fpcdefs.inc}
interface
uses
cclasses,
aasmbase,
procinfo,
cpupi;
type
tllvmprocinfo = class(tcpuprocinfo)
private
fexceptlabelstack: tfplist;
public
constructor create(aparent: tprocinfo); override;
destructor destroy; override;
procedure pushexceptlabel(lab: TAsmLabel);
procedure popexceptlabel(lab: TAsmLabel);
function CurrExceptLabel: TAsmLabel; inline;
end;
implementation
uses
globtype,verbose,
symtable;
constructor tllvmprocinfo.create(aparent: tprocinfo);
begin
inherited;
fexceptlabelstack:=tfplist.create;
end;
destructor tllvmprocinfo.destroy;
begin
if fexceptlabelstack.Count<>0 then
Internalerror(2016121301);
fexceptlabelstack.free;
inherited;
end;
procedure tllvmprocinfo.pushexceptlabel(lab: TAsmLabel);
begin
fexceptlabelstack.add(lab);
end;
procedure tllvmprocinfo.popexceptlabel(lab: TAsmLabel);
begin
if CurrExceptLabel<>lab then
internalerror(2016121302);
fexceptlabelstack.count:=fexceptlabelstack.count-1;
end;
function tllvmprocinfo.CurrExceptLabel: TAsmLabel; inline;
begin
result:=TAsmLabel(fexceptlabelstack.last);
if not assigned(result) then
internalerror(2016121703);
end;
begin
cprocinfo:=tllvmprocinfo;
end.

View File

@ -26,7 +26,7 @@ unit nllvmflw;
interface
uses
aasmbase,
aasmbase,aasmdata,
nflw, ncgflw, ncgnstfl;
type
@ -34,6 +34,11 @@ interface
function getasmlabel: tasmlabel; override;
end;
tllvmexceptionstatehandler = class(tcgexceptionstatehandler)
class procedure new_exception(list: TAsmList; const t: texceptiontemps; out exceptstate: texceptionstate); override;
class procedure emit_except_label(list: TAsmList; var exceptionstate: texceptionstate); override;
end;
implementation
@ -42,8 +47,11 @@ implementation
*****************************************************************************}
uses
aasmdata;
systems,
symconst,symdef,llvmdef,
cgbase,cgutils,hlcgobj,
llvmbase,aasmllvm,
procinfo,llvmpi;
function tllvmlabelnode.getasmlabel: tasmlabel;
begin
@ -61,7 +69,73 @@ implementation
result:=asmlabel
end;
{*****************************************************************************
tllvmexceptionstatehandler
*****************************************************************************}
class procedure tllvmexceptionstatehandler.new_exception(list: TAsmList; const t: texceptiontemps; out exceptstate: texceptionstate);
var
landingpadlabel: TAsmLabel;
begin
inherited;
{ all calls inside the exception block have to be invokes instead,
which refer to the exception label. We can't use the same label as the
one used by the setjmp/longjmp, because only invoke operations are
allowed to refer to a landingpad label -> create an extra label and
emit:
landingpadlabel:
%reg = landingpad ..
exceptstate.exceptionlabel:
<exception handling code>
}
current_asmdata.getjumplabel(landingpadlabel);
{ for consistency checking when popping }
tllvmprocinfo(current_procinfo).pushexceptlabel(exceptstate.exceptionlabel);
tllvmprocinfo(current_procinfo).pushexceptlabel(landingpadlabel);
end;
class procedure tllvmexceptionstatehandler.emit_except_label(list: TAsmList; var exceptionstate: texceptionstate);
var
reg: tregister;
clause: taillvm;
exc: treference;
landingpaddef: trecorddef;
begin
{ prevent fallthrough into the landingpad, not allowed }
hlcg.a_jmp_always(list,exceptionstate.exceptionlabel);
hlcg.a_label(list,tllvmprocinfo(current_procinfo).CurrExceptLabel);
{ indicate that we will catch everything to LLVM's control flow
analysis; our personality function will (for now) indicate that it
doesn't actually want to handle any exceptions, so the stack unwinders
will ignore us anyway (our own exceptions are still handled via
setjmp/longjmp) }
clause:=taillvm.exceptclause(
la_catch,voidpointertype,nil,nil);
{ dummy register (for now): we use the same code as on other platforms
to determine the exception type, our "personality function" won't
return anything useful }
reg:=hlcg.getintregister(list,u32inttype);
{ use packrecords 1 because we don't want padding (LLVM 4.0+ requires
exactly two fields in this struct) }
landingpaddef:=llvmgettemprecorddef([voidpointertype,u32inttype],
1,
targetinfos[target_info.system]^.alignment.recordalignmin,
targetinfos[target_info.system]^.alignment.maxCrecordalign);
list.concat(taillvm.landingpad(reg,landingpaddef,clause));
{ remove current exception label from the stack }
tllvmprocinfo(current_procinfo).popexceptlabel(tllvmprocinfo(current_procinfo).CurrExceptLabel);
{ consistency check }
tllvmprocinfo(current_procinfo).popexceptlabel(exceptionstate.exceptionlabel);
inherited;
end;
begin
clabelnode:=tllvmlabelnode;
cexceptionstatehandler:=tllvmexceptionstatehandler;
end.